Doxygen: Documenting single API that has multiple implementations - comments

Suppose I have one header file with a couple of functions and multiple source files that implement the functions that the header provided.
I would like to document the functions using Doxygen, but only the general comments regarding all implementations, not implementation specific.
What is the best way to see only the header comments? I can't set configuration to ignore all source files as some other source files in the projects don't have headers at all.
For example:
api.h
/**
* #details
* This is general comment for header
*
*********************************************************************/
implemenation1.c
/**
* #details
* This is implementation specific comment for file 1
*
*********************************************************************/
int foo(int a, int b)
{
...
}
implemenation2.c
/**
* #details
* This is implementation specific comment for file 2
*
*********************************************************************/
int foo(int a, int b)
{
...
}
I want to see only that comment on Doxygen:
This is general comment for header
Thanks in advance!

The best solultion I've found so far is this:
api.h
/**
* #details
* This is general comment for header
*
*********************************************************************/
implemenation1.c
/**
* #details
* This is implementation specific comment for file 1
*
* #cond
*********************************************************************/
int foo(int a, int b)
{
...
}
/** #endcond */
implemenation2.c
/**
* #details
* This is implementation specific comment for file 2
*
* #cond
*********************************************************************/
int foo(int a, int b)
{
...
}
/** #endcond */

Related

Need help understanding stack frame layout

While implementing a stack walker for a debugger I am working on I reached the point to extract the arguments to a function call and display them. To make it simple I started with the cdecl convention in pure 32-bit (both debugger and debuggee), and a function that takes 3 parameters. However, I cannot understand why the arguments in the stack trace are out of order compared to what cdecl defines (right-to-left, nothing in registers), despite trying to figure it out for a few days now.
Here is a representation of the function call I am trying to stack trace:
void Function(unsigned long long a, const void * b, unsigned int c) {
printf("a=0x%llX, b=%p, c=0x%X\n", a, b, c);
_asm { int 3 }; /* Because I don't have stepping or dynamic breakpoints implemented yet */
}
int main(int argc, char* argv[]) {
Function(2, (void*)0x7A3FE8, 0x2004);
return 0;
}
This is what the function (unsurprisingly) printed to the console:
a=0x2, c=0x7a3fe8, c=0x2004
This is the stack trace generated at the breakpoint (the debugger catches the breakpoint and there I try to walk the stack):
0x3EF5E0: 0x10004286 /* previous pc */
0x3EF5DC: 0x3EF60C /* previous fp */
0x3EF5D8: 0x7A3FE8 /* arg b --> Wait... why is b _above_ c here? */
0x3EF5D4: 0x2004 /* arg c */
0x3EF5D0: 0x0 /* arg a, upper 32 bit */
0x3EF5CC: 0x2 /* arg a, lower 32 bit */
The code that's responsible for dumping the stack frames (implemented using the DIA SDK, though, I don't think that is relevant to my problem) looks like this:
ULONGLONG stackframe_top = 0;
m_frame->get_base(&stackframe_top); /* IDiaStackFrame */
/* dump 30 * 4 bytes */
for (DWORD i = 0; i < 30; i++)
{
ULONGLONG address = stackframe_top - (i * 4);
DWORD value;
SIZE_T read_bytes;
if (ReadProcessMemory(m_process, reinterpret_cast<LPVOID>(address), &value, sizeof(value), &read_bytes) == TRUE)
{
debugprintf(L"0x%llX: 0x%X\n", address, value); /* wrapper around OutputDebugString */
}
}
I am compiling the test program without any optimization in vs2015 update 3.
I have validated that I am indeed compiling it as cdecl by looking in the pdb with the dia2dump sample application.
I do not understand what is causing the stack to look like this, it doesn't match anything I learned, nor does it match the documentation provided by Microsoft.
I also checked google a whole lot (including osdev wiki pages, msdn blog posts, and so on), and checked my (by now probably outdated) books on 32-bit x86 assembly programming (that were released before 64-bit CPUs existed).
Thank you very much in advance for any explanations or links!
I had somehow misunderstood where the arguments to a function call end up in memory compared to the base of the stack frame, as pointed out by Raymond. This is the fixed code snippet:
ULONGLONG stackframe_top = 0;
m_frame->get_base(&stackframe_top); /* IDiaStackFrame */
/* dump 30 * 4 bytes */
for (DWORD i = 0; i < 30; i++)
{
ULONGLONG address = stackframe_top + (i * 4); /* <-- Read before the stack frame */
DWORD value;
SIZE_T read_bytes;
if (ReadProcessMemory(m_process, reinterpret_cast<LPVOID>(address), &value, sizeof(value), &read_bytes) == TRUE)
{
debugprintf(L"0x%llX: 0x%X\n", address, value); /* wrapper around OutputDebugString */
}
}

std::function has no member named 'target'

I am trying to store list of unique function pointers. An obvious wrapper to pure pointers seem std::function.
As it turns out, std::functions cannot be compared.
Then a simple comparison of the raw pointers should work, right? Maybe, but I am getting the following error for the following code. My compiler is gcc 4.7.2. Is this something that was not implemented back in 2012?
std::function<void(bool)> f;
void(*p)(bool) = f.target<void(*)(bool)>();
error: 'class std::function' has no member named 'target'
Here is the relevant except from the header:
#ifdef __GXX_RTTI
// [3.7.2.5] function target access
/**
* #brief Determine the type of the target of this function object
* wrapper.
*
* #returns the type identifier of the target function object, or
* #c typeid(void) if #c !(bool)*this.
*
* This function will not throw an %exception.
*/
const type_info& target_type() const noexcept;
/**
* #brief Access the stored target function object.
*
* #return Returns a pointer to the stored target function object,
* if #c typeid(Functor).equals(target_type()); otherwise, a NULL
* pointer.
*
* This function will not throw an %exception.
*/
template<typename _Functor> _Functor* target() noexcept;
/// #overload
template<typename _Functor> const _Functor* target() const noexcept;
#endif
I had this problem as well. RTTI needs to be enabled in the compiler flags.
I had -fno-rtti in the compiler flags.

Listing block devices inside a Kernel module

I am writing a kernel module that lists block devices and their corresponding dev_t which I will use for tracing.
The following is the structure block_device
struct block_device {
dev_t bd_dev; /* not a kdev_t - it's a search key */
int bd_openers;
struct inode * bd_inode; /* will die */
struct super_block * bd_super;
struct mutex bd_mutex; /* open/close mutex */
struct list_head bd_inodes;
void * bd_claiming;
void * bd_holder;
int bd_holders;
bool bd_write_holder;
#ifdef CONFIG_SYSFS
struct list_head bd_holder_disks;
#endif
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
/* number of times partitions within this device have been opened. */
unsigned bd_part_count;
int bd_invalidated;
struct gendisk * bd_disk;
struct request_queue * bd_queue;
struct list_head bd_list;
............
};
bd_list is a linked list containing all block devices in the system. all_bdevs ( fs/block_dev.c ) is the head of the list but the problem that it's not exported.
Is there a way to iterate block devices inside a kernel module ?

Can't debug after using SysTick_Config

I - an embedded beginner - am fighting my way through the black magic world of embedded programming. So far I won already a bunch of fights, but this new bug seems to be a hard one.
First, my embedded setup:
Olimex STM32-P207 (STM32F207)
Olimex ARM-USB-OCD-H JTAG
OpenOCD
Eclipse (with CDT and GDB hardware debugging)
Codesourcery Toolchain
Startup file and linker script (adapted memory map for the STM32F207) for RIDE (what uses GCC)
STM32F2xx_StdPeriph_Lib_V1.1.0
Using the many tutorials and Q&As out there I was able to set-up makefile, linker and startup code and got some simple examples running using STM's standard library (classic blinky, using buttons and interrupts etc.). However, once I started playing around with the SysTick interrupts, things got messy.
If add the SysTick_Config() call to my code (even with an empty SysTick_Handler), ...
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
[...]
*/
if (SysTick_Config(SystemCoreClock / 120000))
{
// Catch config error
while(1);
}
[...]
... then my debugger starts at the (inline) function NVIC_SetPriority() and once I hit "run" I end up in the HardFault_Handler().
This only happens, when using the debugger. Otherwise the code runs normal (telling from the blinking LEDs).
I already read a lot and tried a lot (modifying compiler options, linker, startup, trying other code with SysTick_Config() calls), but nothing solved this problem.
One thing could be a hint:
The compiler starts in both cases (with and without the SysTick_Config call) at 0x00000184. In the case without the SysTick_Config call this points at the beginnig of main(). Using SysTick_Config this pionts at NVIC_SetPriority().
Does anybody have a clue what's going on? Any hint about where I could continue my search for a solution?
I don't know what further information would be helpful to solve this riddle. Please let me know and I will be happy to provide the missing pieces.
Thanks a lot!
/edit1: Added results of arm-none-eabi-readelf, -objdump and -size.
/edit2: I removed the code info to make space for the actual code. With this new simplified version debugging starts at
08000184: stmdaeq r0, {r4, r6, r8, r9, r10, r11, sp}
readelf:
[ 2] .text PROGBITS 08000184 008184 002dcc 00 AX 0 0 4
...
2: 08000184 0 SECTION LOCAL DEFAULT 2
...
46: 08000184 0 NOTYPE LOCAL DEFAULT 2 $d
main.c
/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t counter = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void assert_failed(uint8_t* file, uint32_t line);
void Delay(__IO uint32_t nCount);
void SysTick_Handler(void);
/**
* #brief Main program
* #param None
* #retval None
*/
int main(void)
{
if (SysTick_Config(SystemCoreClock / 12000))
{
// Catch config error
while(1);
}
/*
* Configure the LEDs
*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); // LEDs
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIOF->BSRRL = GPIO_Pin_6;
while (1)
{
if (GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_9) == SET)
{
GPIOF->BSRRH = GPIO_Pin_9;
}
else
{
GPIOF->BSRRL = GPIO_Pin_9;
}
Delay(500000);
}
return 0;
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* #brief Delay Function.
* #param nCount:specifies the Delay time length.
* #retval None
*/
void Delay(__IO uint32_t nCount)
{
while (nCount > 0)
{
nCount--;
}
}
/**
* #brief This function handles Hard Fault exception.
* #param None
* #retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
/**
* #brief This function handles SysTick Handler.
* #param None
* #retval None
*/
void SysTick_Handler(void)
{
if (counter > 10000 )
{
if (GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_8) == SET)
{
GPIOF->BSRRH = GPIO_Pin_8;
}
else
{
GPIOF->BSRRL = GPIO_Pin_8;
}
counter = 0;
}
else
{
counter++;
}
}
/edit3:
Soultion:
Because the solution is burrowed in a comment, I put it up here:
My linker file was missing ENTRY(your_function_of_choice); (e.g. Reset_Handler). Adding this made my debugger work again (it now starts at the right point).
Thanks everybody!
I have a strong feeling that the entry point isn't specified correctly in the compiler options or linker script...
And whatever code comes first at link time in the ".text" section, it gets to have the entry point.
The entry point, however, should point to a special "init" function that would set up the stack, initialize the ".bss" section (and maybe some other sections as well), initialize any hardware that's necessary for basic operation (e.g. the interrupt controller and maybe some system timer) and any remaining portions of the and standard libraries before actually transferring control to main().
I'm not familiar with the tools and your hardware, so I can't say exactly what that special "init" function is, but that's pretty much the problem. It's not being pointed to by the entry point of the compiled program. NVIC_SetPriority() doesn't make any sense there.

Dynamic array inside dynamic structure array in c

I am stuck trying to figure out how to initialize a pointer to a 3d array inside a 2d structure array. I had it working fine when I could declare the structure like this:
#define ROUSSEAU 300
#define OSSO 500
#define MOJO 9000
typedef struct x_primitive
{
short avg[ROUSSEAU][OSSO][MOJO];
} xprimitive;
But unfortunately the structure is too large to declare as a global. So I have to calloc the memory (192GB memory available on the system: win 7 64 bit);
typedef struct x_primitive
{
short ***avg;
} xprimitive;
xprimitive **xPmtv, *_xPmtv;
void xallocatePmtvMemory(void)
{
int structureCount = 10;
unsigned __int64 pmtvStructureSize = ROUSSEAU * OSSO * MOJO * sizeof(short);
unsigned __int64 memoryBlockSize = structureCount * pmtvStructureSize;
_xPmtv = (xprimitive *) calloc(structureCount, pmtvStructureSize);
xPmtv = (xprimitive **) calloc(structureCount, sizeof(xprimitive *));
for ( int i = 0; i < structureCount; ++i)
{
unsigned __int64 index = i * pmtvStructureSize;
xPmtv[i] = &_xPmtv[ index ];
// **************** here is the problem ******
xPmtv[i]->avg[ROUSSEAU][OSSO][MOJO] = &_xPmtv[ index + (ROUSSEAU + OSSO + MOJO) ];
}
}
I am trying to assign the "avg" variable to a chunk of memory, and utterly failing.
Pointers and arrays aren't interchangeable in the way you seem to be wanting them to be. I think you can probably be doing something much simpler. Make avg into a pointer:
typedef struct x_primitive
{
short (*avg)[ROUSSEAU][OSSO][MOJO];
} xprimitive;
And then allocate the space for the array at runtime:
xprimitive xPmtv;
xPmtv.avg = calloc(1, ROUSSEAU * OSSO * MOJO * sizeof(short));
Using it is a bit funny looking, though:
(*xPmtv.avg)[1][2][3]
If you have multiple structures, just throw the initialization into a loop. Maybe a better idea is to use a flexible array member to keep the usage syntax looking a bit more normal - it will cost you a dummy entry in the structure - flexible array members aren't allowed to play around on their own. Then again, why do you have a structure with only one field anyway?
typedef struct x_primitive
{
int dummyEntry;
short avg[][OSSO][MOJO];
} xprimitive;
To allocate one, you'd use:
xprimitive *xPmtv = calloc(1, sizeof(xprimitive) + ROUSSEAU * OSSO * MOJO * sizeof(short));
And access the array something like:
xPmtv->avg[1][2][3]

Resources