Core dump note section - gdb

Following my question about manually generating a core dump file, I decided to dive into it and get my hands dirty.
I am able to build the basic core dump structure and get my dead program's memory back into the core dump within a big LOAD section. When debugging in GDB, my variables are back, no problem with that.
Here comes the tricky part, how do I get GDB to retrieve information about where the program was when it crashed.
I know that the note section of the core dump contains this information (cpu registers among others). Here is what a objdump -h gives for a "real" core dump :
core.28339: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 note0 000001e8 00000000 00000000 000000f4 2**0
CONTENTS, READONLY
1 .reg/28339 00000044 00000000 00000000 00000150 2**2
CONTENTS
2 .reg 00000044 00000000 00000000 00000150 2**2
CONTENTS
3 .auxv 000000a0 00000000 00000000 0000023c 2**2
CONTENTS
4 load1a 00001000 08010000 00000000 00001000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
.. other load sections ...
I figured out thanks to readelf that those .reg sections contain data mapped from some structures :
Notes at offset 0x000000f4 with length 0x000001e8:
Owner Data size Description
CORE 0x00000090 NT_PRSTATUS (prstatus structure)
CORE 0x0000007c NT_PRPSINFO (prpsinfo structure)
CORE 0x000000a0 NT_AUXV (auxiliary vector)
Can someone give me directions on how is structured the Notes section ?
I tried writing directly those structures to my file, it did not work and I am obviously missing something here.
I looked at the Google Coredumper code and took some bits of it, but writing the note section is not that simple and any detailed information about what it exactly contains and its format are welcomed.
Edit #1 : following 1st comment
I figured out my Elf file should be structured as follows :
Elf header ElfW(Ehdr)
Program headers (Ehdr.e_phnum times ElfW(Phdr)), here i basically used one PT_NOTE and one PT_LOAD headers
Note sections :
Section's header (ElfW(Nhdr))
Section's name (.n_namesz long)
Section's data (.n_descsz long)
Program section containing all my program's memory
Then i will have to put 3 note records, one for the prstatus, one for prpsinfo and one for the auxiliary vector.
This seems to be the right way as readelf gives me a similar output as what I got above with the real core dump.
Edit #2 : after getting the correct structure
I am now struggling with the different structures composing the note records.
Here is what I get when running a eu-readelf --notes on my core dump :
Note segment of 540 bytes at offset 0x74:
Owner Data size Type
CORE 336 PRSTATUS
CORE 136 PRPSINFO
CORE 8 AUXV
NULL
Here is what I get when running the same command on the real core dump :
Note segment of 488 bytes at offset 0xf4:
Owner Data size Type
CORE 144 PRSTATUS
info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
sigpend: <>
sighold: <>
pid: 28339, ppid: 41446, pgrp: 28339, sid: 41446
utime: 0.000000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
orig_eax: -1, fpvalid: 0
ebx: -1 ecx: 0 edx: 0
esi: 0 edi: 0 ebp: 0xffb9fcbc
eax: -1 eip: 0x08014b26 eflags: 0x00010286
esp: 0xffb9fcb4
ds: 0x002b es: 0x002b fs: 0x0000 gs: 0x0000 cs: 0x0023 ss: 0x002b
CORE 124 PRPSINFO
state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00400400
uid: 9432, gid: 6246, pid: 28339, ppid: 41446, pgrp: 28339, sid: 41446
fname: pikeos_app, psargs: ./pikeos_app
CORE 160 AUXV
SYSINFO: 0xf7768420
SYSINFO_EHDR: 0xf7768000
HWCAP: 0xbfebfbff <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe>
PAGESZ: 4096
CLKTCK: 100
PHDR: 0x8010034
PHENT: 32
PHNUM: 2
BASE: 0
FLAGS: 0
ENTRY: 0x80100be
UID: 9432
EUID: 9432
GID: 6246
EGID: 6246
SECURE: 0
RANDOM: 0xffb9ffab
EXECFN: 0xffba1feb
PLATFORM: 0xffb9ffbb
NULL
Does someone have any clue or explanations about why my note records are not read properly ?
I thought it might be due to incorrect offsets, but then why would the records be correctly listed ?
Thanks !

Was having same troubles some time ago with my project of converting CRIU images into core dumps. It is fully written in python(even elf structures are in ctypes), so it could be used as a guide. See https://github.com/efiop/criu-coredump .I.e. how everything is structured could be seen here https://github.com/efiop/criu-coredump/blob/master/criu_coredump/core_dump.py .

Can someone give me directions on how is structured the Notes section?
The notes section is a concatenation of variable-sized note records. Each note record begins with ElfW(Nhdr) structure, followed by (variable sized) name (of length .n_namesz, padded so total size of name on disk is divisible by 4) and data (of length .n_descsz, similarly padded).

After some tests I figured things out, answering for anyone looking for this information :
Can someone confirm I am going the right way structuring my Elf file this way ?
Yes.
As GDB is accepting the file, this seems to be the right way of doing. Results shown by readelf -a show the correct structure, good so far.
I am not sure about where should lay the data (note & program sections) into my file : is there a mandatory order, or is this my program headers offset that define where the data is ?
Offsets given to Phdr.p_offset should point where the data lays in the Elf file. They start at the very beginning of the file.
For example :
The p_offset for the PT_NOTE program header should be set at sizeof(ElfW(Ehdr)) + ehdr.e_phnum*sizeof(ElfW(Phdr)). ehdr.e_phnum being the number of program header present in the Elf file.
For the PT_LOAD program header, this is a bit longer, cause we will also have to add length of all the note sections. For a "standard" core dump with a note segment containg NT_PRSTATUS, NT_PRPSINFO and NT_AUXV sections, offset for the PT_LOAD data (Phdr.p_offset) will be :
sizeof(ElfW(Ehdr)) + ehdr.e_phnum*sizeof(ElfW(Phdr))
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct prstatus)
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct prpsinfo)
+ sizeof(ElfW(Nhdr)) + sizeof(name_of_section) + sizeof(struct auxv_t)

Related

ARM Cortex-M HardFault exception on writting halfword to flash using C++

I've written a project using C++ to run on ARM Cortex-M (STM32F0) but I had some problems with accessing defined buffers as class members though I resolved that by defining them as global vars.
But now I'm completely stuck with this new problem which I don't know what to do with it.
I've a code to unlock flash and write something into it and close it. If I implement it in C file and run it through C nature (call from main.c) it works perfect. but calling that through C++ files (whether written inside C or C++ source file) it will throw a HardFault Exception.
static uint32_t waitForLastOperation(uint32_t msDelay)
{
while (READ_BIT(FLASH->SR, FLASH_SR_BSY) && msDelay)
{
LL_mDelay(1);
msDelay--;
}
/* Check FLASH End of Operation flag */
if (READ_BIT((FLASH->SR), (FLASH_SR_EOP)))
{
/* Clear FLASH End of Operation pending bit */
(FLASH->SR) = (FLASH_SR_EOP);
}
if (READ_BIT((FLASH->SR),
(FLASH_SR_WRPERR)) || READ_BIT((FLASH->SR), (FLASH_SR_PGERR)))
{
FLASH->SR = 0U;
return 0;
}
/* There is no error flag set */
return 1;
}
uint32_t programHalfWord(uint16_t data, uint32_t address)
{
uint32_t status;
/* Proceed to program the new data */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Write data in the address */
*(__IO uint16_t*) address = data;
/* Wait for last operation to be completed */
status = waitForLastOperation(FLASH_TIMEOUT);
if (READ_BIT(FLASH->SR, FLASH_SR_EOP))
FLASH->SR = FLASH_SR_EOP;
/* If the program operation is completed, disable the PG Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
return status;
}
uint32_t flash_unlock()
{
if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) == RESET)
return 1;
/* Authorize the FLASH Registers access */
WRITE_REG(FLASH->KEYR, FLASH_KEY1);
WRITE_REG(FLASH->KEYR, FLASH_KEY2);
/* Verify Flash is unlocked */
if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
return 0;
return 1;
}
and this is how I use it:
if(flash_unlock())
{
programHalfWord(0x11, 0x8007C00);
}
It throws exception right after executing *(__IO uint16_t*) address = data;.
Flash is erased at this address, address is aligned (it's actually start of a sector). I've checked everything to make sure that flash is unlocked but it seems that there's something with the code compiled in C++.
I'm using arm-none-eabi-gcc and arm-none-eabi-g++ to compile my code.
Thanks in advance
Update:
Here's the list of flags being used with g++ compiler:
-mcpu=cortex-m0 -std=gnu++14 -g3 -DSTM32F030x6 -DHSE_STARTUP_TIMEOUT=100 -DLSE_STARTUP_TIMEOUT=5000 -DDEBUG -DLSE_VALUE=32768 -DDATA_CACHE_ENABLE=0 -DINSTRUCTION_CACHE_ENABLE=0 -DVDD_VALUE=3300 -DLSI_VALUE=40000 -DHSI_VALUE=8000000 -DUSE_FULL_LL_DRIVER -DPREFETCH_ENABLE=1 -DHSE_VALUE=2000000 -c -I../app/Inc -I../Inc -I../Drivers/STM32F0xx_HAL_Driver/Inc -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F0xx/Include -I../app/Driver -Og -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-threadsafe-statics -fno-use-cxa-atexit -Wall -fno-short-enums -fstack-usage --specs=nano.specs -mfloat-abi=soft -mthumb
And this is for gcc:
-mcpu=cortex-m0 -std=gnu11 -g3 -DSTM32F030x6 -DHSE_STARTUP_TIMEOUT=100 -DLSE_STARTUP_TIMEOUT=5000 -DDEBUG -DLSE_VALUE=32768 -DDATA_CACHE_ENABLE=0 -DINSTRUCTION_CACHE_ENABLE=0 -DVDD_VALUE=3300 -DLSI_VALUE=40000 -DHSI_VALUE=8000000 -DUSE_FULL_LL_DRIVER -DPREFETCH_ENABLE=1 -DHSE_VALUE=2000000 -c -I../app/Inc -I../Inc -I../Drivers/STM32F0xx_HAL_Driver/Inc -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F0xx/Include -I../app/Driver -Og -ffunction-sections -fdata-sections -Wall -fno-short-enums -fstack-usage --specs=nano.specs -mfloat-abi=soft -mthumb
and g++ linker:
-mcpu=cortex-m0 -T"./STM32F030K6TX_FLASH.ld" -Wl,-Map="${ProjName}.map" -Wl,--gc-sections -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group
Since it is difficult to analyze the issue without having access to your hardware / software setup, I can only make wild guesses and provide some hints, after having some troubles with STM32 flash programming as well recently (on a different STM32 model (STM32F215RET6)). - But I'm not an expert in this area at all, and I've only used the vendor supplied HAL driver to access the internal flash so far.
The error might be caused by a memory bus error.
It would be interesting to verify if that's case with a debugger (e.g. by reading the flash status register (FLASH_SR), right after the error occurred).
The question is: Why does your C code work, when compiled with gcc and why not, when compiled with g++? I guess, it might have something to do with a technical detail, that the compiler "doesn't know" about the underlying restrictions of the architecture / memory model.
The STM32F030K6T reference manual (RM0360) says, in section "3.2.2 Flash program and erase operations, Main Flash memory programming":
The main Flash memory can be programmed 16 bits at a time. The program operation is started when the CPU writes a half-word into a main Flash memory address with the PG bit of the FLASH_CR register set. Any attempt to write data that are not half-word long will result in a bus error generating a Hard Fault interrupt.
So, 32-bit write access to the internal flash will cause a Hard Fault interrupt.
When you compile the project with assembly listing generation enabled, you could analyze what's exactly going in your C++ variant, and compare it to the generated machine code of the C variant.
Since I've been working on a STM32 flash related issue recently as well, I've looked up what's going on in the vendor supplied flash code in my case (stm32f2xx_hal_flash.c), and it turns out, that the main write operation to the flash (*(__IO uint16_t*)Address = Data;) is translated to the matching ARM half-word store instruction strh, like expected:
strh r1, [r0]
This could be verified by looking at the auto-generated assembly listings for the ST supplied FLASH_Program_HalfWord() function in stm32f2xx_hal_flash.c. It looks like that (compiled with GCC with no optimization and debugging information -Og):
662:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
663:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** {
140 .loc 1 663 1 is_stmt 1 view -0
141 .cfi_startproc
142 # args = 0, pretend = 0, frame = 0
143 # frame_needed = 0, uses_anonymous_args = 0
144 # link register save eliminated.
664:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** /* Check the parameters */
665:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** assert_param(IS_FLASH_ADDRESS(Address));
145 .loc 1 665 3 view .LVU27
666:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c ****
667:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** /* If the previous operation is completed, proceed to program the new data */
668:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
146 .loc 1 668 3 view .LVU28
147 0000 074B ldr r3, .L9
148 0002 1A69 ldr r2, [r3, #16]
149 0004 22F44072 bic r2, r2, #768
150 0008 1A61 str r2, [r3, #16]
669:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** FLASH->CR |= FLASH_PSIZE_HALF_WORD;
151 .loc 1 669 3 view .LVU29
152 .loc 1 669 13 is_stmt 0 view .LVU30
153 000a 1A69 ldr r2, [r3, #16]
154 000c 42F48072 orr r2, r2, #256
155 0010 1A61 str r2, [r3, #16]
670:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** FLASH->CR |= FLASH_CR_PG;
156 .loc 1 670 3 is_stmt 1 view .LVU31
157 .loc 1 670 13 is_stmt 0 view .LVU32
158 0012 1A69 ldr r2, [r3, #16]
159 0014 42F00102 orr r2, r2, #1
160 0018 1A61 str r2, [r3, #16]
671:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c ****
672:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** *(__IO uint16_t*)Address = Data;
161 .loc 1 672 3 is_stmt 1 view .LVU33
162 .loc 1 672 28 is_stmt 0 view .LVU34
163 001a 0180 strh r1, [r0] # movhi
673:Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c **** }
164 .loc 1 673 1 view .LVU35
165 001c 7047 bx lr
166 .L10:
167 001e 00BF .align 2
168 .L9:
169 0020 003C0240 .word 1073888256
170 .cfi_endproc
The generated machine code could be disassembled and inspected with objdump, without all the annotations, like that:
$ arm-none-eabi-objdump -d -j .text.FLASH_Program_HalfWord build/stm32f2xx_hal_flash.o
build/stm32f2xx_hal_flash.o: file format elf32-littlearm
Disassembly of section .text.FLASH_Program_HalfWord:
00000000 <FLASH_Program_HalfWord>:
0: 4b07 ldr r3, [pc, #28] ; (20 <FLASH_Program_HalfWord+0x20>)
2: 691a ldr r2, [r3, #16]
4: f422 7240 bic.w r2, r2, #768 ; 0x300
8: 611a str r2, [r3, #16]
a: 691a ldr r2, [r3, #16]
c: f442 7280 orr.w r2, r2, #256 ; 0x100
10: 611a str r2, [r3, #16]
12: 691a ldr r2, [r3, #16]
14: f042 0201 orr.w r2, r2, #1
18: 611a str r2, [r3, #16]
1a: 8001 strh r1, [r0, #0]
1c: 4770 bx lr
1e: bf00 nop
20: 40023c00 .word 0x40023c00
It would be interesting, if you could find out how it looks like in your object file compiled as C++. Is it also using the strh instruction?
By the way, all the ARM instructions are documented also be ST in the STM32F0xxx Cortex-M0 programming manual (PM0215):
The Cortex-M0 processor implements the ARMv6-M architecture, which is based on the 16-bit Thumb® instruction set and includes Thumb-2 technology.
STRHRt, [Rn, <Rm|#imm>] Store register as halfword
And as a reference, also in the ARM®v6-M Architecture Reference Manual of course.
Side note 1:
The reference manual says that address 0x8007C00 is right at the beginning of flash page 31, in flash sector 7, assuming a STM32F030K6Tx chip is used:
Forgetting about this could cause issues, if the sector is write protected via flash option bytes (but that obviously wasn't the case, since it works fine in the C variant). Just for the sake of completeness (you've already commented on that), a quote from the reference manual, "4.1.3 Write protection option byte":
This set of registers is used to write-protect the Flash memory.
Clearing a bit in WRPx field (and at the same time setting a
corresponding bit in nWRPx field) will write-protect the given memory
sector. For STM32F030x4, STM32F030x6, STM32F070x6, STM32F030x8 and
STM32F070xB devices, WRP bits from 0 to 31 are protecting the
Flash memory by sector of 4 kB.
(Possibly unrelated, but also worth mentioning: beware of the different conditions present when Read Protection (RDP) Level 2 or Level 3 is active. RDP is a different protection mechanism, separate from the sector protection via flash option bytes, or lock state of the flash. Reading the flash from a debugger or when executing form RAM will cause a Hard Fault when RDP Level 2 or 3 is used. Documented in the reference manual, section "3.3.1 Read protection".)
Side note 2:
You could try to mix the official HAL C driver code or your own tested flash related C code, and the new C++ parts of the project, and check if the problem still occurs.
(Be careful when mixing C and C++, and always take care of naming mangeling by using extern "C" { ... }, related post: https://stackoverflow.com/a/1041880/5872574)
Side note 3:
Like already mentioned, I've recently had an unrelated issue with flash programming as well. And saw strange bus errors (in the status register after a Hard Fault). I also made sure that the flash was unlocked, and not write protected. If I remember correctly, I had to add this in front of my erase / write operations (but I do not remember exactly and can't find it right now). It was a necessary but strange fix, because there was no operation in progress, besides regular program execution (from flash).
while (FLASH_WaitForLastOperation(100) != HAL_OK) {
HAL_IWDG_Refresh(&hiwdg);
}
This issue possibly had something to do with the way the STM32 uses the flash with a prefetch buffer / wait states / instruction cache and the data cache like described in the reference manual (see also: FLASH_ACR register). I didn't investigate the issue any further. Just make sure that there is no flash operation pending/active when a write/erase access is initiated.
Also interesting to note, program/erase operations will prevent any read access to the bus (flash memory), but they will not cause an error, like described in the reference manual, in section "3.2.2 Flash program and erase operations":
An ongoing Flash memory operation will not block the CPU as long as
the CPU does not access the Flash memory.
On the contrary, during a program/erase operation to the Flash memory,
any attempt to read the Flash memory will stall the bus. The read
operation will proceed correctly once the program/erase operation has
completed. This means that code or data fetches cannot be made while a
program/erase operation is ongoing.
For program and erase operations on the Flash memory (write/erase),
the internal RC oscillator (HSI) must be ON.
EDIT:
In order to check whether there's really enough flash memory left to write to, and that the area is really unused by the running binary itself, these commands could come in handy, meant as a future reference (using my test binary for an STM32F215RET here):
$ arm-none-eabi-strip build/prj.elf
$ arm-none-eabi-objdump -h build/prj.elf
build/prj.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .isr_vector 00000184 08000000 08000000 00010000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 000134a0 08000188 08000188 00010188 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .rodata 00002968 08013628 08013628 00023628 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .ARM 00000008 08015f90 08015f90 00025f90 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .init_array 00000004 08015f98 08015f98 00025f98 2**2
CONTENTS, ALLOC, LOAD, DATA
5 .fini_array 00000004 08015f9c 08015f9c 00025f9c 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .data 000002c0 20000000 08015fa0 00030000 2**3
CONTENTS, ALLOC, LOAD, DATA
7 .bss 0000149c 200002c0 08016260 000302c0 2**3
ALLOC
8 ._user_heap_stack 00000604 2000175c 08016260 0003175c 2**0
ALLOC
9 .ARM.attributes 00000029 00000000 00000000 000302c0 2**0
CONTENTS, READONLY
10 .comment 0000001e 00000000 00000000 000302e9 2**0
CONTENTS, READONLY
0x08016260 marks the end of the used flash memory by the binary.
That can be verified with arm-none-eabi-size:
$ arm-none-eabi-size build/prj.elf
text data bss dec hex filename
90004 712 6816 97532 17cfc build/prj.elf
$ echo $((90004 + 712))
90716
$ echo $((0x08016260 - 0x08000000 - (90004 + 712)))
4
So, with 2**3 -> 8 byte alignment and a flash base address of 0x08000000, that means that 90720 bytes of flash memory are actually used by the binary.
To find out which of the flash sectors are left unused, it is now easy to look the address up directly in the "Flash memory organization" table in the reference manual.
In my case, the linker script was modified to make sure that only half of the flash is used, like that:
$ cat STM32F215RETx_FLASH.ld
(...)
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K /* keep 256K free at the end */
/* FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K */
}
(...)
That way you'll get a linker error if the binary gets too large.
I had the same issue. My mistake was invalid alignment.
I'm assured 90% of such a errors is alignment issues, especially on Cortex-M0.
I've made proper alignment of my strucrure inside C++ class and it was enough.
Note: functions executed in RAM, like write half page, should better be inside extern "C" {} expression.

Accessing particular section in ELF

We have a program in which a section is added named .proghead.
I can read elf .proghead section data by using following command,
$ readelf -x .proghead elf-binary-file
Hex dump of section '.proghead':
0x0058b960 00112233 00000000 00010000 00000000 .."3............
0x0058b970 15200704 00000000 00016904 00000000 . ........i.....
Now I have to access this section using a C/C++ program.
Can someone please help me in writing C/C++ code to read particular section in elf binary ?
Any help is highly appreciated .
What you need is to read section headers (Elf64_Shdr) to find section names and its offset. The relevant information lies in sh_name and sh_offset fields. So you need to compare sh_name with your required section. On finding required section, you can get its offset(sh_offset) and its size sh_size. Now it is easy for you to get data through loop which reads from sh_offset to sh_offset+sh_offset+sh_size. This is theoretically correct and hope you will get data of required section For further help check following links Get elf sections offsets How to get a pointer to an specific section of a program from within itself? (Maybe with libelf)
You can copy one section of the binary to a text file using the command objcopy from package binutils:
$ objcopy -O binary --only-section=<section> <binary> <output>
So in your case:
$ objcopy -O binary --only-section=.proghead elf-binary-file output.proghead
After that, you can simply code a C++ program that reads a binary file. This approach would work as long as all you need to do is to read that section and not to modify the binary.
If you need to modify the binary, you would need to start reading the section at that sections's offset for size bytes. It's possible to use readelf to know what offset a section starts and its size:
$ readelf --wide -S /bin/ls
There are 28 section headers, starting at offset 0x1c760:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 000254 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 0000000000400274 000274 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 000298 000068 00 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400300 000300 000c18 18 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400f18 000f18 000593 00 A 0 0 1
However, bear in mind that directly modifying a binary is fine as long as there's no new data added or data removed. Adding new data, will grow a section which results into overriding data of other sections and disorganizing the section index. Shrinking a section and filling up with padding may be OK but doing in the .text section, for instance, may affect the program's logic if there's a jump to a relative direction that no longer exists.
in general, modify the linker command file to give a name to the first address of the .proghead section.
Then, in the C file write a struct to cover the contents of the .proghead section.
Then set a C pointer variable, of the above struct type, to point to the .proghead section.
From then on, that pointer->fieldName will access each of the fields in the struct that is the .proghead section

Reading Dump file through Debug engine API

I have written a small program using Debug engine API to read a dump file.
I am executing !analyze -v command through code.
I am able to get almost every detail that could be extracted with above command but not the Process Name and Image name and module name
I really don't know where I'm going wrong.
Things i tried:
copied the dll's ext,exts,Kdexts,kext to the same folder where my exe is
present.
also copied the symsrv.dll.
for symbol path i am using
symbols->SetSymbolPath("srv*http://msdl.microsoft.com/download/symbols") where symbols is an IDebugSymbols pointer
But so far it didn't work.
The result i'm getting is :
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
CRITICAL_OBJECT_TERMINATION (f4) A process or thread crucial to system
operation has unexpectedly exited or been terminated. Several
processes and threads are necessary for the operation of the system;
when they are terminated (for any reason), the system can no longer
function. Arguments: Arg1: 00000003, Process Arg2: 84d97860,
Terminating object Arg3: 84d979cc, Process image file name Arg4:
8285cec0, Explanatory message (ascii)
Debugging Details:
------------------
***** Debugger could not find nt in module list, module list might be incorrect, error 0x80070057.
-----------------------------------------------
| NT symbols are not available |
| reduced functionality |
| |
------------------------------------------------
unable to get nt!KiCurrentEtwBufferOffset
unable to get nt!KiCurrentEtwBufferBase
PROCESS_OBJECT: 84d97860
IMAGE_NAME: Unknown_Image
DEBUG_FLR_IMAGE_TIMESTAMP: 0
FAULTING_MODULE: 00000000
CUSTOMER_CRASH_COUNT: 1
DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT
BUGCHECK_STR: 0xF4
CURRENT_IRQL: 0
STACK_TEXT: WARNING: Frame IP not in any known module. Following
frames may be wrong. 950dbc9c 829223af 000000f4 00000003 84d97860
0x82722bfc 950dbcc0 828a0009 8285cec0 84d979cc 84d97ad0 0x829223af
950dbcf0 8289ff4c 84d97860 8447b030 00000001 0x828a0009 950dbd24
826818c6 000001e0 00000001 001cebb0 0x8289ff4c 950dbd34 77be70f4
badb0d00 001ceba8 00000000 0x826818c6 950dbd38 badb0d00 001ceba8
00000000 00000000 0x77be70f4 950dbd3c 001ceba8 00000000 00000000
00000000 0xbadb0d00 950dbd40 00000000 00000000 00000000 00000000
0x1ceba8
STACK_COMMAND: kb
BUCKET_ID: CORRUPT_MODULELIST
MODULE_NAME: Unknown_Module *** Followup info cannot be found !!!
Please contact "Debugger Team"

c/c++: How can I know the size of used flash memory?

I recently faced flash overflow problem. After doing some optimization in code, I saved some flash memory and executed software successfully. I want to how much flash memory is saved through my changes. Please let me know how can I check for used flash / available flash memory. Also I want to how much flash is utilized by particular function/file.
Below mentioned are some info about my developing environment.
- Avr microcontroller with 64 k ram and 512 K flash.
- Using freeRtos.
- Using GNU C++ compiler.
- Using AVRATJTAGEICE for programming and Debugging.
Please let me know the solution.
Regards,
Jagadeep.
GCC's size program is what you're looking for.
size can be passed the full compiled .elf file. It will, by default, output something like this:
$ size linked-file.elf
text data bss dec hex filename
11228 112 1488 12828 321c linked-file.elf
This is saying:
There are 11228 bytes in the .text "section" of this file. This is generally for functions.
There are 112 bytes of initialized data: global variables in the program with initial values.
There are 1488 bytes of uninitialized data: global variables without initial values.
dec is simply the sum of the previous 3 values: 11228 + 112 + 1488 = 12828.
hex is simply the hexadecimal representation of the dec value: 0x321c == 12828.
For embedded systems, generally dec needs to be smaller than the flash size of your target device (or the available space on the device).
It is generally sufficient to simply watch the dec or text outputs of GCC's size command to monitor the size of your compiled code over time. A large jump in size often indicates a poorly implemented new feature or constexpr that are not getting compiled away. (Don't forget function-sections and data-sections).
Note: For AVR's, you'll want to use avr-size for checking the linked size of AVR .elf files. avr-size takes an extra argument of the target chip and will automatically calculate the percentage of used flash for your chosen chip.
GCC's size also works directly on intermediate object files.
This is particularly useful if you want to check the compiled size of functions.
You should see something like this excerpt:
$ size -A main.cpp.o
main.cpp.o :
section size addr
.group 8 0
.group 8 0
.text 0 0
.data 0 0
.bss 0 0
.text._Z8sendByteh 8 0
.text._ZN3XMC5IOpin7setModeENS0_4ModeE 64 0
.text._ZN7NamSpac6OptionIN5Clock4TimeEEmmEi 76 0
.text.Default_Handler 24 0
.text.HardFault_Handler 16 0
.text.SVC_Handler 16 0
.text.PendSV_Handler 16 0
.text.SysTick_Handler 28 0
.text._Z5errorPKc 8 0
.text._ZN7NamSpac5Motor2goEi 368 0
.text._ZN7NamSpac5Motor3getEv 12 0
.rodata.cst1 1 0
.text.startup.main 632 0
.text._ZN7NamSpac7Program3runEv 380 0
.text._ZN7NamSpac8Position4tickEv 24 0
.text.startup._GLOBAL__sub_I__ZN7NamSpac7displayE 292 0
.init_array 4 0
.bss._ZN5Debug9formatterE 4 0
.rodata._ZL10dispDigits 8 0
.bss.position 4 0
.bss.motorState 4 0
.bss.count 4 0
.rodata._ZL9diameters 20 0
.bss._ZN7NamSpac8diameterE 16 0
.bss._ZN5Debug3pinE 12 0
.bss._ZN7NamSpac7displayE 24 0
.rodata.str1.4 153 0
.rodata._ZL12dispSegments 32 0
.bss._ZL16diametersDisplay 10 0
.bss.loadAggregate 4 0
.bss.startCount 4 0
.bss._ZL15runtimesDisplay 10 0
.bss._ZN7NamSpac7runtimeE 16 0
.bss.startTime 4 0
.rodata._ZL8runtimes 20 0
.comment 111 0
.ARM.attributes 49 0
Total 2494
Please let me know the solution.
Sorry, there's no the solution! You've gotta getting through what's linked to your final ELF, and decide if it was linked by intend, or unwanted default.
Please let me know how can I check for used flash / available flash memory.
That primarily depends on your actual target hardware platform, so you have to manage to get your .text section fitting in there.
Also I want to how much flash is utilized by particular function/file.
The nm tool of the GCC binutils provides detailed information about any (global) symbol found in an ELF file and the space it occupies in it's associated section. You'll just need to grep the results for particular functions/classes/namespaces (best demangled!) to accumulate section type and symbol filtered outputs for analysis.
That's the approach, I've been using for a little tool called nmalyzr. Sorry to say, as it stands on the GIT repo, its not really working as intended (I've got working versions, that aren't pushed back).
In general, it's a good strategy to chase for code that has #include <iostream> statements (no matter if std::cout or alike are used or not, static instances are provided!), or unwanted newlib/libstdc++ bindings as for e.g. default exception handling.
Use size command from binutils on the generated elf file. As you seem to use an AVR chip, use avr-size.
To get the size of functions, use nm command from binutils (avr-nm on AVR chips).

Need to get process memory using c++

I want to calculate my process memory (rss) at runtime in my application (c++/unix/multithreaded).Do we have any API to use for that.Please note that , I am aware of reading /proc/stat and getrusage() , but dont want to read/parse a system file from appication and getrusage() does not work in my linux distribution.
The whole intent was to check for memory leak caused by my application . I have even tried tracking memory by overloading new/malloc/calloc/realloc and get the memory allocation trakced, but even with thsese I am not able to track the whole memory allocated by process. It would be also helpfull if you can suggest the other probable areas where I should look for memory allocation/ memory leak other than the above stated APIs.
I am aware of Valgrind/mpatrol type of memory monitor tools .. but unfortunately it does not work with my application..
Thanks in advance
First, this kind of information is operating system specific. It has to be done differently on Linux, on MacOSX, on FreeBSD...
On Linux, the blessed way, is as every one told you, to use the /proc file system, which is how all the system utilities (e.g. top or ps) are retrieving that information (perhaps by using libproc which is just a wrapper around reads of /proc/ files).
Could you explain why reading e.g. /proc/self/statm or /proc/self/stat or /proc/self/status or /proc/self/maps is not possible for you?
Remember that these /proc/files are pseudo-files, and no actual slow I/O operation to disk is involved in reading them. And you have to read them sequentially, seeking (or stat-ing) them does not work.
It seems to me that
long process_size_in_pages(void)
{
long s = -1;
FILE *f = fopen("/proc/self/statm", "r");
if (!f) return -1;
// if for any reason the fscanf fails, s is still -1,
// with errno appropriately set.
fscanf(f, "%ld", &s);
fclose (f);
return s;
}
is the fastest way to retrieve that information. Why can't you do that?
You could use valgrind. By setting it in monitor mode and calling remote method (gdb) monitor full, it would give you the total, allocated, memory at run time. See this page for more information.
You can read /proc/${pid}/status, it looks like
Name: nginx
State: S (sleeping)
SleepAVG: 98%
Tgid: 11884
Pid: 11884
PPid: 11883
TracerPid: 0
Uid: 99 99 99 99
Gid: 99 99 99 99
FDSize: 64
Groups: 99
VmPeak: 23932 kB
VmSize: 23932 kB
VmLck: 0 kB
VmHWM: 4276 kB
VmRSS: 4276 kB
VmData: 3744 kB
VmStk: 88 kB
VmExe: 452 kB
VmLib: 3024 kB
VmPTE: 88 kB
StaBrk: 1a931000 kB
Brk: 1a974000 kB
StaStk: 7fffc224d560 kB
Threads: 1
SigQ: 0/73712
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000040001000
SigCgt: 0000000198016a07
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,0000000f
Mems_allowed: 00000000,00000001
You can parse the VmRSS value.