I use OpenOCD + GDB to debug the firmware. When I type load it loads the code to the FLASH memory:
Loading section ExtFlashSection, size 0x3fe000 lma 0x90000000
Loading section .isr_vector, size 0x1f8 lma 0x8000000
Loading section .text, size 0x19978 lma 0x8000200
Loading section .rodata, size 0x52d0 lma 0x8019b78
Loading section .ARM, size 0x8 lma 0x801ee48
Loading section .init_array, size 0x10 lma 0x801ee50
Loading section .fini_array, size 0x4 lma 0x801ee60
Loading section TextFlashSection, size 0x8 lma 0x801ee64
Loading section FontFlashSection, size 0x30b1c lma 0x801ee6c
Loading section .data, size 0x9c lma 0x804f988
Start address 0x80005f0, load size 4512284
Transfer rate: 89 KB/sec, 2926 bytes/write.
However, I want the ExtFlashSection to be not loaded, because I load it manually by external tool (it extracts the contents from the ELF and flashes). I tried adding NOLOAD attribute to that section, but then it is not present in the final ELF file (so I can not extract it).
How to tell GDB or OpenOCD to discard the contents of ExtFlashSection?
Related
I've set "ulimit -c unlimited" on my Fedora system so segfaults generate core dump files. This is working.
I've seen an NT_FILE note mentioned at these URLs:
ELF core file format
Anatomy of an ELF core file
But my core files only contain these notes:
$ readelf --notes core.simple.11
Notes at offset 0x000003f8 with length 0x00000558:
Owner Data size Description
CORE 0x00000150 NT_PRSTATUS (prstatus structure)
CORE 0x00000088 NT_PRPSINFO (prpsinfo structure)
CORE 0x00000130 NT_AUXV (auxiliary vector)
CORE 0x00000200 NT_FPREGSET (floating point registers)
Why is there no NT_FILE note? How can I figure out the various object files the core file may be based on, and more importantly, the virtual addresses where those files were mapped into the core image?
Without the address mapping information from the NT_FILE note, I don't know how I can perform code address lookups in the DWARF debugging info from the object files.
Program headers in the core file:
$ readelf --segments core.simple.11
Elf file type is CORE (Core file)
Entry point 0x0
There are 17 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NOTE 0x00000000000003f8 0x0000000000000000 0x0000000000000000
0x0000000000000558 0x0000000000000000 0
LOAD 0x0000000000001000 0x0000000000400000 0x0000000000000000
0x0000000000001000 0x0000000000001000 R E 1000
LOAD 0x0000000000002000 0x0000000000600000 0x0000000000000000
0x0000000000001000 0x0000000000001000 RW 1000
LOAD 0x0000000000003000 0x00000035fe800000 0x0000000000000000
0x0000000000001000 0x000000000001e000 R E 1000
LOAD 0x0000000000004000 0x00000035fea1d000 0x0000000000000000
0x0000000000001000 0x0000000000001000 R 1000
LOAD 0x0000000000005000 0x00000035fea1e000 0x0000000000000000
0x0000000000001000 0x0000000000001000 RW 1000
LOAD 0x0000000000006000 0x00000035fea1f000 0x0000000000000000
0x0000000000001000 0x0000000000001000 RW 1000
LOAD 0x0000000000007000 0x00000035fec00000 0x0000000000000000
0x0000000000001000 0x0000000000173000 R E 1000
LOAD 0x0000000000008000 0x00000035fed73000 0x0000000000000000
0x0000000000000000 0x00000000001ff000 1000
LOAD 0x0000000000008000 0x00000035fef72000 0x0000000000000000
0x0000000000004000 0x0000000000004000 R 1000
LOAD 0x000000000000c000 0x00000035fef76000 0x0000000000000000
0x0000000000001000 0x0000000000001000 RW 1000
LOAD 0x000000000000d000 0x00000035fef77000 0x0000000000000000
0x0000000000005000 0x0000000000005000 RW 1000
LOAD 0x0000000000012000 0x00007fc22db59000 0x0000000000000000
0x0000000000003000 0x0000000000003000 RW 1000
LOAD 0x0000000000015000 0x00007fc22db6c000 0x0000000000000000
0x0000000000001000 0x0000000000001000 RW 1000
LOAD 0x0000000000016000 0x00007fff81c40000 0x0000000000000000
0x0000000000016000 0x0000000000016000 RW 1000
LOAD 0x000000000002c000 0x00007fff81dee000 0x0000000000000000
0x0000000000001000 0x0000000000001000 R E 1000
LOAD 0x000000000002d000 0xffffffffff600000 0x0000000000000000
0x0000000000000000 0x0000000000001000 R E 1000
Program headers in the executable file:
$ readelf --segments simple
Elf file type is EXEC (Executable file)
Entry point 0x400390
There are 8 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001c0 0x00000000000001c0 R E 8
INTERP 0x0000000000000200 0x0000000000400200 0x0000000000400200
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000674 0x0000000000000674 R E 200000
LOAD 0x0000000000000678 0x0000000000600678 0x0000000000600678
0x00000000000001e4 0x00000000000001f8 RW 200000
DYNAMIC 0x00000000000006a0 0x00000000006006a0 0x00000000006006a0
0x0000000000000190 0x0000000000000190 RW 8
NOTE 0x000000000000021c 0x000000000040021c 0x000000000040021c
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x00000000000005a8 0x00000000004005a8 0x00000000004005a8
0x000000000000002c 0x000000000000002c R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
My Linux version:
$ uname -a
Linux somehost 2.6.32.23-170.fc12.x86_64 #1 SMP Mon Sep 27 17:23:59 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
Why is there no NT_FILE note?
As noted by Mark Plotnick, it's a fairly recent kernel addition.
In no way is NT_FILE note required for GDB (in fact, current GDB doesn't appear to use NT_FILE at all, except when writing a core file with gcore command).
How can I figure out the various object files the core file may be based on, and more importantly, the virtual addresses where those files were mapped into the core image?
The way this works for GDB is to look at PT_DYNAMIC for the main executable in the core, extract DT_DEBUG from that, which then gives it a pointer to _r_debug, which includes a linked list r_map of struct link_map, with each node in the list describing a loaded ELF file.
The (gdb) info shared command will show you the decoded version of above info, but you need to provide matching binaries: the core alone does not contain sufficient info.
Now, your question isn't very clear and could be understood several different ways.
It could be: "I have a core, which application crashed?" Use file core and hope that the first 16 characters of pathname are sufficient. If that isn't sufficient, running strings core will often reveal which application produced it. You should also consider setting /proc/sys/kernel/core_pattern to something that includes %e or %E, so the question is trivial to answer in the future.
It could be: "I have several versions of application foo, and want to know which version of foo produced this particular core". In that case, you should be linking foo with -Wl,--build-id linker flag. That flag creates NT_GNU_BUILD_ID note in the foo binary. That note survives strip, and is saved inside the core file as well. You can then run eu-unstrip -n --core /path/to/core, and that will produce output like this:
eu-unstrip -n --core core
0x400000+0x208000 c266a51e4b85b16ca17bff8328f3abeafb577b29#0x400284 - - [exe]
0x7ffe3f7d9000+0x1000 7f14688f101a2ace5cad23dfbfbc918616651576#0x7ffe3f7d9340 . - linux-vdso.so.1
0x7fb5b6ec3000+0x2241c8 d0f537904076d73f29e4a37341f8a449e2ef6cd0#0x7fb5b6ec31d8 /lib64/ld-linux-x86-64.so.2 /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.19.so ld-linux-x86-64.so.2
0x7fb5b6afe000+0x3c42c0 cf699a15caae64f50311fc4655b86dc39a479789#0x7fb5b6afe280 /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so libc.so.6
From above output, you can know both exactly which ELF binaries were used, and where in memory they were loaded.
P.S. I just tried dumping a core from a.out built with -Wl,--build-id=none, and the resulting eu-unstrip output is still quite useful:
eu-unstrip -n --core core
0x400000+0x202000 - - - [exe]
0x7fff5e1a0000+0x1000 7f14688f101a2ace5cad23dfbfbc918616651576#0x7fff5e1a0340 . - linux-vdso.so.1
0x7fbda432d000+0x2241c8 d0f537904076d73f29e4a37341f8a449e2ef6cd0#0x7fbda432d1d8 /lib64/ld-linux-x86-64.so.2 /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.19.so ld-linux-x86-64.so.2
0x7fbda3f68000+0x3c42c0 cf699a15caae64f50311fc4655b86dc39a479789#0x7fbda3f68280 /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so libc.so.6
Update:
There is no PT_DYNAMIC program header in my core file itself,
No, but PT_DYNAMIC is a writable segment #0x6006a0. That segment is actually written to (by the dynamic loader), and thus is always saved in the core (as other modified data).
In your case, the contents is in the PT_LOAD segment #0x600000 (i.e. the segment at file offset 0x2000 in the core).
I set a watch point on memory location in gdb and load a application through gdb load command. watch point does not hit during load command although memory location is being changed during loading of application.
(gdb) watch *0x1c
Hardware watchpoint 2: *0x1c
(gdb) p/x *0x1c
$2 = 0xffffffff
(gdb) load
Loading section .text, size 0x53b4 lma 0x0
Loading section .eh_frame, size 0x4 lma 0x53b4
Loading section .ARM.exidx, size 0x8 lma 0x53b8
Loading section .rodata, size 0x238 lma 0x53c0
Loading section .data, size 0x520 lma 0x55f8
Start address 0xe4, load size 23320
Transfer rate: 9 KB/sec, 4664 bytes/write.
(gdb) p/x *0x1c
$3 = 0xfdfcdf08
(gdb)
Does watch point work during gdb load command?
I think it would be very unexpected if this triggered. Watchpoints are for changes made by running your program. In this case, your program isn't running, it is being loaded.
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)
Cross compiled gdb, with configure --target=m68k-linux --program-prefix=m68k- , gives error as no core file handler recognizes the format.
Details:
The core file is generated on a m68k devcie and the log is analyzed on the i686-pc-linux-gnu
GDB version - 7.6
Any clue on this subject?
ELf format of the core file is
elf -a core
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: MC68000
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 10
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000174 0x00000000 0x00000000 0x00570 0x00000 0
LOAD 0x002000 0x40000000 0x00000000 0x00000 0x16000 R E 0x2000
LOAD 0x002000 0x40016000 0x00000000 0x04000 0x04000 RW 0x2000
LOAD 0x006000 0x4001a000 0x00000000 0x132000 0x132000 R E 0x2000
LOAD 0x138000 0x4014c000 0x00000000 0x08000 0x08000 RW 0x2000
LOAD 0x140000 0x40154000 0x00000000 0x02000 0x02000 RW 0x2000
LOAD 0x142000 0x80000000 0x00000000 0x00000 0x02000 R E 0x2000
LOAD 0x142000 0x80002000 0x00000000 0x02000 0x02000 RW 0x2000
LOAD 0x144000 0x80004000 0x00000000 0x02000 0x02000 RWE 0x2000
LOAD 0x146000 0xbfffe000 0x00000000 0x02000 0x02000 RWE 0x2000
There is no dynamic segment in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Notes at offset 0x00000174 with length 0x00000570:
Owner Data size Description
CORE 0x0000009a NT_PRSTATUS (prstatus structure)
CORE 0x0000007c NT_PRPSINFO (prpsinfo structure)
CORE 0x00000310 NT_TASKSTRUCT (task structure)
CORE 0x00000078 NT_AUXV (auxiliary vector)
CORE 0x0000006c NT_FPREGSET (floating point registers)
p.s with older gdb version 6.3 i get an error - GDB can't read core files on this machine.
Judging by presence of "NT_TASKSTRUCT" note, that is likely a kernel crash core. You probably need crash or similar tool.
When loading an executable onto a board using OpenOCD and GDB, I get something similar to (snippet taken from here):
$ arm-none-eabi-gdb example.elf
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
...
(gdb) monitor reset halt
...
(gdb) load
Loading section .vectors, size 0x100 lma 0x20000000
Loading section .text, size 0x5a0 lma 0x20000100
Loading section .data, size 0x18 lma 0x200006a0
Start address 0x2000061c, load size 1720
Transfer rate: 22 KB/sec, 573 bytes/write.
(gdb) continue
Continuing.
...
What does lma mean in this context?
That means "Local Memory Address", which is the address in memory where code or data has been loaded to:
http://www.embeddedrelated.com/usenet/embedded/show/77071-1.php