Why does gdb do not show all RISC-V CSRs when debugging bare-metal program running on qemu? - gdb

Recently I'm learning about RISC-V AIA architecture and I need to do some test to verify the curious points that I found in AIA SPEC. Since QEMU is the only hardware simulator (maybe this is not accurate)supporting the RISC-V AIA arch(as far as I know), I've tried to run some bare-metal programs on Qemu in system mode, my start param for Qemu is as below:
qemu-system-riscv64 -cpu rv64,h=true -nographic -M virt,aia=aplic-imsic -m 512M -bios none -kernel ${test_name}.elf -s -S
The program runs as normal. However, when I use i all-r to check the status of some H-extension CSRs, I found nothing:
zero 0x0 0
ra 0x0 0x0
sp 0x0 0x0
gp 0x0 0x0
tp 0x0 0x0
t0 0x0 0
t1 0x0 0
t2 0x0 0
fp 0x0 0x0
s1 0x0 0
a0 0x0 0
a1 0x0 0
a2 0x0 0
a3 0x0 0
a4 0x0 0
a5 0x0 0
a6 0x0 0
a7 0x0 0
s2 0x0 0
s3 0x0 0
s4 0x0 0
s5 0x0 0
s6 0x0 0
s7 0x0 0
s8 0x0 0
s9 0x0 0
s10 0x0 0
s11 0x0 0
t3 0x0 0
t4 0x0 0
t5 0x0 0
t6 0x0 0
pc 0x1000 0x1000
ft0 {float = 0, double = 0} (raw 0x0000000000000000)
ft1 {float = 0, double = 0} (raw 0x0000000000000000)
ft2 {float = 0, double = 0} (raw 0x0000000000000000)
ft3 {float = 0, double = 0} (raw 0x0000000000000000)
ft4 {float = 0, double = 0} (raw 0x0000000000000000)
ft5 {float = 0, double = 0} (raw 0x0000000000000000)
ft6 {float = 0, double = 0} (raw 0x0000000000000000)
ft7 {float = 0, double = 0} (raw 0x0000000000000000)
fs0 {float = 0, double = 0} (raw 0x0000000000000000)
fs1 {float = 0, double = 0} (raw 0x0000000000000000)
fa0 {float = 0, double = 0} (raw 0x0000000000000000)
fa1 {float = 0, double = 0} (raw 0x0000000000000000)
fa2 {float = 0, double = 0} (raw 0x0000000000000000)
--Type <RET> for more, q to quit, c to continue without paging--
fa3 {float = 0, double = 0} (raw 0x0000000000000000)
fa4 {float = 0, double = 0} (raw 0x0000000000000000)
fa5 {float = 0, double = 0} (raw 0x0000000000000000)
fa6 {float = 0, double = 0} (raw 0x0000000000000000)
fa7 {float = 0, double = 0} (raw 0x0000000000000000)
fs2 {float = 0, double = 0} (raw 0x0000000000000000)
fs3 {float = 0, double = 0} (raw 0x0000000000000000)
fs4 {float = 0, double = 0} (raw 0x0000000000000000)
fs5 {float = 0, double = 0} (raw 0x0000000000000000)
fs6 {float = 0, double = 0} (raw 0x0000000000000000)
fs7 {float = 0, double = 0} (raw 0x0000000000000000)
fs8 {float = 0, double = 0} (raw 0x0000000000000000)
fs9 {float = 0, double = 0} (raw 0x0000000000000000)
fs10 {float = 0, double = 0} (raw 0x0000000000000000)
fs11 {float = 0, double = 0} (raw 0x0000000000000000)
ft8 {float = 0, double = 0} (raw 0x0000000000000000)
ft9 {float = 0, double = 0} (raw 0x0000000000000000)
ft10 {float = 0, double = 0} (raw 0x0000000000000000)
ft11 {float = 0, double = 0} (raw 0x0000000000000000)
fflags 0x0 RD:0 NV:0 DZ:0 OF:0 UF:0 NX:0
frm 0x0 FRM:0 [RNE (round to nearest; ties to even)]
fcsr 0x0 RD:0 NV:0 DZ:0 OF:0 UF:0 NX:0 FRM:0 [RNE (round to nearest; ties to even)]
sstatus 0x200000000 8589934592
sie 0x0 0
stvec 0x0 0
scounteren 0x0 0
sscratch 0x0 0
sepc 0x0 0
scause 0x0 0
stval 0x0 0
sip 0x0 0
satp 0x0 0
mstatus 0xa00000000 SD:0 VM:00 MXR:0 PUM:0 MPRV:0 XS:0 FS:0 MPP:0 HPP:0 SPP:0 MPIE:0 HPIE:0 SPIE:0 UPIE:0 MIE:0 HIE:0 SIE:0 UIE:0
misa 0x80000000001411ad RV64ACDFHIMSU
medeleg 0x0 0
mideleg 0x0 0
mie 0x0 0
mtvec 0x0 0
mcounteren 0x0 0
mhpmevent3 0x0 0
mhpmevent4 0x0 0
mhpmevent5 0x0 0
mhpmevent6 0x0 0
mhpmevent7 0x0 0
mhpmevent8 0x0 0
mhpmevent9 0x0 0
--Type <RET> for more, q to quit, c to continue without paging--
mhpmevent10 0x0 0
mhpmevent11 0x0 0
mhpmevent12 0x0 0
mhpmevent13 0x0 0
mhpmevent14 0x0 0
mhpmevent15 0x0 0
mhpmevent16 0x0 0
mhpmevent17 0x0 0
mhpmevent18 0x0 0
mhpmevent19 0x0 0
mhpmevent20 0x0 0
mhpmevent21 0x0 0
mhpmevent22 0x0 0
mhpmevent23 0x0 0
mhpmevent24 0x0 0
mhpmevent25 0x0 0
mhpmevent26 0x0 0
mhpmevent27 0x0 0
mhpmevent28 0x0 0
mhpmevent29 0x0 0
mhpmevent30 0x0 0
mhpmevent31 0x0 0
mscratch 0x0 0
mepc 0x0 0
mcause 0x0 0
mtval 0x0 0
mip 0x80 128
pmpcfg0 0x0 0
pmpcfg1 Could not fetch register "pmpcfg1"; remote failure reply 'E14'
pmpcfg2 0x0 0
pmpcfg3 Could not fetch register "pmpcfg3"; remote failure reply 'E14'
pmpaddr0 0x0 0
pmpaddr1 0x0 0
pmpaddr2 0x0 0
pmpaddr3 0x0 0
pmpaddr4 0x0 0
pmpaddr5 0x0 0
pmpaddr6 0x0 0
pmpaddr7 0x0 0
pmpaddr8 0x0 0
pmpaddr9 0x0 0
pmpaddr10 0x0 0
pmpaddr11 0x0 0
pmpaddr12 0x0 0
pmpaddr13 0x0 0
pmpaddr14 0x0 0
--Type <RET> for more, q to quit, c to continue without paging--
pmpaddr15 0x0 0
tselect 0x0 0
tdata1 0x2000000000000000 2305843009213693952
tdata2 0x0 0
tdata3 Could not fetch register "tdata3"; remote failure reply 'E14'
mcycle 0x7bfd8d01bf1f6 2181262762308086
minstret 0x7bfd8d020bee2 2181262762622690
mhpmcounter3 0x0 0
mhpmcounter4 0x0 0
mhpmcounter5 0x0 0
mhpmcounter6 0x0 0
mhpmcounter7 0x0 0
mhpmcounter8 0x0 0
mhpmcounter9 0x0 0
mhpmcounter10 0x0 0
mhpmcounter11 0x0 0
mhpmcounter12 0x0 0
mhpmcounter13 0x0 0
mhpmcounter14 0x0 0
mhpmcounter15 0x0 0
mhpmcounter16 0x0 0
mhpmcounter17 0x0 0
mhpmcounter18 0x0 0
mhpmcounter19 0x0 0
mhpmcounter20 0x0 0
mhpmcounter21 0x0 0
mhpmcounter22 0x0 0
mhpmcounter23 0x0 0
mhpmcounter24 0x0 0
mhpmcounter25 0x0 0
mhpmcounter26 0x0 0
mhpmcounter27 0x0 0
mhpmcounter28 0x0 0
mhpmcounter29 0x0 0
mhpmcounter30 0x0 0
mhpmcounter31 0x0 0
cycle 0x7bfd8d0ba61a4 2181262772691364
time 0x0 0
instret 0x7bfd8d0caa32e 2181262773756718
hpmcounter3 0x0 0
hpmcounter4 0x0 0
hpmcounter5 0x0 0
hpmcounter6 0x0 0
hpmcounter7 0x0 0
hpmcounter8 0x0 0
hpmcounter9 0x0 0
--Type <RET> for more, q to quit, c to continue without paging--
hpmcounter10 0x0 0
hpmcounter11 0x0 0
hpmcounter12 0x0 0
hpmcounter13 0x0 0
hpmcounter14 0x0 0
hpmcounter15 0x0 0
hpmcounter16 0x0 0
hpmcounter17 0x0 0
hpmcounter18 0x0 0
hpmcounter19 0x0 0
hpmcounter20 0x0 0
hpmcounter21 0x0 0
hpmcounter22 0x0 0
hpmcounter23 0x0 0
hpmcounter24 0x0 0
hpmcounter25 0x0 0
hpmcounter26 0x0 0
hpmcounter27 0x0 0
hpmcounter28 0x0 0
hpmcounter29 0x0 0
hpmcounter30 0x0 0
hpmcounter31 0x0 0
mvendorid 0x0 0
marchid 0x70032 458802
mimpid 0x70032 458802
mhartid 0x0 0
priv 0x3 prv:3 [Machine]
senvcfg 0x0 0
menvcfg 0x0 0
mconfigptr 0x0 0
As you can see, I use the -cpu,h=true option to make sure that h-extension is supported in this RISC-V system, and the value of misa can also prove this. I'm curious about why cannot I see any one of H CSRs?
My gdb version is 10.1(riscv64-unknown-elf-gdb,riscv64-unknown-linux-gnu-gdb).And it's 7.0.5 for Qemu.
Could you please help me to solve this problem? Thank you so much.

The set of CSRs that GDB will display is controlled by the target, so QEMU in this case. The target passes an XML description to GDB that describes the set of available registers.
After connecting to QEMU, then, from the GDB prompt, you can ask GDB to print the target description using maintenance print xml-tdesc, this will print the XML document that the QEMU sent. Additionally you can do maintenance print xml-tdesc FILENAME to write the document out to FILENAME.
You should double check this XML file to ensure the registers you expect are not present. My guess is they will be missing. If they are in that file then this is a GDB issue. If the registers are not in that file then the problem is QEMU not telling GDB about the registers.
So QEMU builds the set of CSRs it tells GDB about from this table:
https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/csr.c#L3333
You should check that table for the registers you are expecting. If the registers are not in that table, then QEMU doesn't know about the registers at all. If the registers are in that table then QEMU does know about them, but has decided not to tell GDB for some reason.
The code that converts the table of CSRs into the XML description for GDB can be found here:
https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/gdbstub.c#L318
You'll notice there is some code that decides if a CSR should be included or not:
predicate = csr_ops[i].predicate;
if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
/* Add CSR to XML document. */
}
I don't know QEMU beyond this very top level, so I don't really know what that predicate check is doing.

Related

C++ const char* messes up the multiboot header

This is weird.
So I'm trying to make a little kernel and I decided to use C++ for this. I did everything and I now have an (almost) working VGA Text Mode Driver. Why almost? Because whenever I pass the write method a const char* the multiboot header literally disappears.
And after a bit of fiddling i realized that ANY const char* use makes it go bonkers. Even just a variable.
The weird thing is that if I never create a const char* it just works. I can print individual characters too.
Note: I based on the Bare Bones Tuturial on OSDev.
Here's the relevant code:
# Main.asm
MBALIGN equ 1 << 0
MEMINFO equ 1 << 1
FLAGS equ MBALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)
section .multiboot
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
section .bss
align 16
stack_bottom:
resb 16384
stack_top:
section .text
global _start:function (_start.end - _start)
_start:
mov esp, stack_top
extern kernel_main
call kernel_main
cli
.hang: hlt
jmp .hang
.end:
// Main.cpp
void init() {
Drivers::VGA vga;
vga.putc('h');
vga.write("hello", 5);
}
extern "C" void kernel_main() {
init();
}
// Part of VGA.cpp
void VGA::write(const char* data, size_t size) {
for (size_t i = 0; i < size; i += 1) {
s_buffer[i] = vga_entry(data[i], _color);
}
}
[...]
u16 VGA::vga_entry(unsigned char c, u8 color) {
return (u16)c | (u16)color << 8;
}
# Linker.ld
ENTRY(_start)
SECTIONS {
. = 1M;
.text : ALIGN(4K) {
KEEP(*(.multiboot))
*(.text)
}
.rodata : ALIGN(4K) {
*(.rodata)
}
.data : ALIGN(4K) {
*(.data)
}
.bss : ALIGN(4K) {
*(COMMON)
*(.bss)
}
}
Compiler Options: -target i686-pc-elf -c -IKernel -ffreestanding -nostdlib++ -fno-exceptions -fno-rtti -fno-stack-protector -m32 -fno-use-cxa-atexit
Toolchain: Clang, Nasm and ld.lld
The problem is that ld.lld has a bug(?) or something. It put the rodata section before text, so the multiboot header wouldn't be visible.
Here's the output of readelf -S Kernel with ld.lld
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .rodata.str1.1 PROGBITS 00100000 001000 000001 01 AMS 0 0 1
[ 2] .text PROGBITS 00101000 002000 0002fe 00 AX 0 0 4096
[ 3] .data PROGBITS 00102000 003000 000004 00 WA 0 0 4096
[ 4] .bss NOBITS 00103000 003004 004000 00 WA 0 0 4096
[ 5] .comment PROGBITS 00000000 003004 000029 01 MS 0 0 1
[ 6] .symtab SYMTAB 00000000 003030 0001a0 10 8 14 4
[ 7] .shstrtab STRTAB 00000000 0031d0 000044 00 0 0 1
[ 8] .strtab STRTAB 00000000 003214 00018f 00 0 0 1
And here's the output with system's ld (GNU)
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00100000 001000 0002fe 00 AX 0 0 4096
[ 2] .rodata.str1.1 PROGBITS 001002fe 0012fe 000001 01 AMS 0 0 1
[ 3] .data PROGBITS 00101000 002000 000004 00 WA 0 0 4096
[ 4] .bss NOBITS 00102000 002004 004000 00 WA 0 0 4096
[ 5] .comment PROGBITS 00000000 002004 000015 01 MS 0 0 1
[ 6] .symtab SYMTAB 00000000 00201c 0001f0 10 7 19 4
[ 7] .strtab STRTAB 00000000 00220c 00018f 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 00239b 000044 00 0 0 1

How to get all pixels in connected components by opencv?

I use the new opencv function connectedComponentsWithStats (version 3.0).
How do I get all pixels in connected components?
The result
The third argument of connectedComponentsWithStats, stats, provides you information that will allow you to draw bounding boxes around the labeled regions.
The second argument, labels should contain an image with zeros (black pixels) for non labeled pixels and coloured pixels for the labeled groups of pixels, one colour per label. Bare in mind, the non-zero values will be unique, but quite small (e.g for 7 labels, starting at 0 (background), the label values will go up to 6).
Here's an example 9x9 binary image:
[
[255,255, 0, 0, 0, 0, 0,255,255],
[255, 0, 0,255,255,255, 0, 0,255],
[ 0, 0,255, 0, 0, 0,255, 0, 0],
[ 0,255, 0, 0,255, 0, 0,255, 0],
[ 0,255, 0,255,255,255, 0,255, 0],
[ 0,255, 0, 0,255, 0, 0,255, 0],
[ 0, 0,255, 0, 0, 0,255, 0, 0],
[255, 0, 0,255,255,255, 0, 0,255],
[255,255, 0, 0, 0, 0, 0,255,255]
]
the connected components labels are:
[
[1 1 0 0 0 0 0 3 3]
[1 0 0 2 2 2 0 0 3]
[0 0 2 0 0 0 2 0 0]
[0 2 0 0 4 0 0 2 0]
[0 2 0 4 4 4 0 2 0]
[0 2 0 0 4 0 0 2 0]
[0 0 2 0 0 0 2 0 0]
[5 0 0 2 2 2 0 0 6]
[5 5 0 0 0 0 0 6 6]
]
to visualise them via imshow you might want to scale those values up.
(could be a look-up table of colours you choose or computed colours as long as they are different enough to visually make sense).
Here's an example of scaling the labels above by 42 (255 max value / 6 foreground labels):
[
[ 42 42 0 0 0 0 0 126 126]
[ 42 0 0 84 84 84 0 0 126]
[ 0 0 84 0 0 0 84 0 0]
[ 0 84 0 0 168 0 0 84 0]
[ 0 84 0 168 168 168 0 84 0]
[ 0 84 0 0 168 0 0 84 0]
[ 0 0 84 0 0 0 84 0 0]
[210 0 0 84 84 84 0 0 252]
[210 210 0 0 0 0 0 252 252]
]

gdb add-symbol-file all sections and load address

I'm debugging a boot loader (syslinux) with gdb and the gdb-stub of qemu. At some point the main file load a shared object ldlinux.elf.
I would like to add the symbols in gdb for that file. The command add-symbol-file seems like the way to go. However, as a relocatable file, I have to specify the memory address it has been loaded at. And here comes the problem.
Although I know the base address at which the LOAD segment has been loaded at, add-symbol-file works section-wise and want me to specify the address at which each section has been loaded.
Can I tell gdb to load all the symbols of all the sections provided that I specify the base address of the file in memory?
Does the behavior of gdb make sens? The section headers aren't used for running an ELF and are even optional. I can't see a use case where specifying the load address of the sections would be useful.
Example
Here are the program headers and section headers of the shared object.
Elf file type is DYN (Shared object file)
Entry point 0x4c60
There are 3 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x1db10 0x20bfc RWE 0x1000
DYNAMIC 0x01d618 0x0001d618 0x0001d618 0x00098 0x00098 RW 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Section to Segment mapping:
Segment Sections...
00 .gnu.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text .rodata .ctors .dtors .data.rel.ro .dynamic .got .got.plt .data .bss
01 .dynamic
02
There are 29 section headers, starting at offset 0x78618:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .gnu.hash GNU_HASH 00000094 000094 0007e0 04 A 2 0 4
[ 2] .dynsym DYNSYM 00000874 000874 0015c0 10 A 3 1 4
[ 3] .dynstr STRTAB 00001e34 001e34 0010f4 00 A 0 0 1
[ 4] .rel.dyn REL 00002f28 002f28 000ce8 08 A 2 0 4
[ 5] .rel.plt REL 00003c10 003c10 000568 08 AI 2 6 4
[ 6] .plt PROGBITS 00004180 004180 000ae0 04 AX 0 0 16
[ 7] .text PROGBITS 00004c60 004c60 013816 00 AX 0 0 4
[ 8] .rodata PROGBITS 00018480 018480 00462f 00 A 0 0 32
[ 9] .ctors INIT_ARRAY 0001cab0 01cab0 000010 00 WA 0 0 4
[10] .dtors FINI_ARRAY 0001cac0 01cac0 000004 00 WA 0 0 4
[11] .data.rel.ro PROGBITS 0001cae0 01cae0 000b38 00 WA 0 0 32
[12] .dynamic DYNAMIC 0001d618 01d618 000098 08 WA 3 0 4
[13] .got PROGBITS 0001d6b0 01d6b0 0000d0 04 WA 0 0 4
[14] .got.plt PROGBITS 0001d780 01d780 0002c0 04 WA 0 0 4
[15] .data PROGBITS 0001da40 01da40 0000d0 00 WA 0 0 32
[16] .bss NOBITS 0001db20 01db10 0030dc 00 WA 0 0 32
[17] .comment PROGBITS 00000000 01db10 000026 01 MS 0 0 1
[18] .debug_aranges PROGBITS 00000000 01db38 0010c0 00 0 0 8
[19] .debug_info PROGBITS 00000000 01ebf8 021ada 00 0 0 1
[20] .debug_abbrev PROGBITS 00000000 0406d2 009647 00 0 0 1
[21] .debug_line PROGBITS 00000000 049d19 00bd3a 00 0 0 1
[22] .debug_frame PROGBITS 00000000 055a54 004574 00 0 0 4
[23] .debug_str PROGBITS 00000000 059fc8 00538c 01 MS 0 0 1
[24] .debug_loc PROGBITS 00000000 05f354 01312d 00 0 0 1
[25] .debug_ranges PROGBITS 00000000 072481 0005d0 00 0 0 1
[26] .shstrtab STRTAB 00000000 072a51 000101 00 0 0 1
[27] .symtab SYMTAB 00000000 072b54 003530 10 28 504 4
[28] .strtab STRTAB 00000000 076084 002593 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
If I try to load the file at the address 0x7fab000 then it will relocate the symbols so that the .text section starts at 0x7fab000.
(gdb) add-symbol-file bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
add symbol table from file "bios/com32/elflink/ldlinux/ldlinux.elf" at
.text_addr = 0x7fab000
(y or n) y
Reading symbols from bios/com32/elflink/ldlinux/ldlinux.elf...done.
And then all the symbols are off by 0x4c60 bytes.
So, finally, I made my own command with python and the readelf tool. It's not very clean since it runs readelf in a subprocess and parse its output instead of parsing the ELF file directly, but it works (for 32 bits ELF only).
It uses the section headers to generate and run an add-symbol-file command with all the sections correctly relocated. The usage is pretty simple, you give it the elf file and the base address of the file. And since the remove-symbol-file wasn't working properly by just giving it the filename, I made a remove-symbol-file-all that generate and run the right remove-symbol-file -a address command.
(gdb) add-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
add symbol table from file "bios/com32/elflink/ldlinux/ldlinux.elf" at
.text_addr = 0x7fafc50
.gnu.hash_addr = 0x7fab094
.dynsym_addr = 0x7fab874
.dynstr_addr = 0x7face34
.rel.dyn_addr = 0x7fadf28
.rel.plt_addr = 0x7faec08
.plt_addr = 0x7faf170
.rodata_addr = 0x7fc34e0
.ctors_addr = 0x7fc7af0
.dtors_addr = 0x7fc7b00
.data.rel.ro_addr = 0x7fc7b20
.dynamic_addr = 0x7fc8658
.got_addr = 0x7fc86f0
.got.plt_addr = 0x7fc87bc
.data_addr = 0x7fc8a80
.bss_addr = 0x7fc8b60
(gdb) remove-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
Here is the code to be added in the .gdbinit file.
python
import subprocess
import re
def relocatesections(filename, addr):
p = subprocess.Popen(["readelf", "-S", filename], stdout = subprocess.PIPE)
sections = []
textaddr = '0'
for line in p.stdout.readlines():
line = line.decode("utf-8").strip()
if not line.startswith('[') or line.startswith('[Nr]'):
continue
line = re.sub(r' +', ' ', line)
line = re.sub(r'\[ *(\d+)\]', '\g<1>', line)
fieldsvalue = line.split(' ')
fieldsname = ['number', 'name', 'type', 'addr', 'offset', 'size', 'entsize', 'flags', 'link', 'info', 'addralign']
sec = dict(zip(fieldsname, fieldsvalue))
if sec['number'] == '0':
continue
sections.append(sec)
if sec['name'] == '.text':
textaddr = sec['addr']
return (textaddr, sections)
class AddSymbolFileAll(gdb.Command):
"""The right version for add-symbol-file"""
def __init__(self):
super(AddSymbolFileAll, self).__init__("add-symbol-file-all", gdb.COMMAND_USER)
self.dont_repeat()
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
filename = argv[0]
if len(argv) > 1:
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
else:
offset = 0
(textaddr, sections) = relocatesections(filename, offset)
cmd = "add-symbol-file %s 0x%08x" % (filename, int(textaddr, 16) + offset)
for s in sections:
addr = int(s['addr'], 16)
if s['name'] == '.text' or addr == 0:
continue
cmd += " -s %s 0x%08x" % (s['name'], addr + offset)
gdb.execute(cmd)
class RemoveSymbolFileAll(gdb.Command):
"""The right version for remove-symbol-file"""
def __init__(self):
super(RemoveSymbolFileAll, self).__init__("remove-symbol-file-all", gdb.COMMAND_USER)
self.dont_repeat()
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
filename = argv[0]
if len(argv) > 1:
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
else:
offset = 0
(textaddr, _) = relocatesections(filename, offset)
cmd = "remove-symbol-file -a 0x%08x" % (int(textaddr, 16) + offset)
gdb.execute(cmd)
AddSymbolFileAll()
RemoveSymbolFileAll()
end
Can I tell gdb to load all the symbols of all the sections provided that I specify the base address of the file in memory?
Yes, but you need to provide the address of .text section, i.e. 0x7fab000+0x00004c60 here. I agree: it's quite annoying to have to fish out address of .text, and I wanted to fix it many times, so that e.g.
(gdb) add-symbol-file foo.so #0x7abc0000
just works. Feel free to file a feature request in GDB bugzilla.
Does the behavior of gdb make sens?
I am guessing that this is rooted in how GDB was used to debug embedded ROMs, where each section can be at arbitrary memory address.

core dump with same pattern

My application crashes once in a while and generates coredump.
Each time stack is different. But each time when it dumps, i find that one of the pointer will be corrupt. and each time first 4 bytes of pointer value will be 0X100 (256). By this i can make out that this dump is because of memory corruption. But i have no idea as how to proceed. I ran all the static tools on the code. But i cant really attach valgrind (I have no access to site)
#0 0x00002b5775455738 in _STL::_List_base<int, _STL::allocator<int> >::clear (this=0x2b576debd408) at /home/enipcore/core/add-ons/include/stlport/stl/_list.c:72
72 in /home/xxxx/core/add-ons/include/stlport/stl/_list.c
(gdb) info locals
__tmp = 0x10084a957f0
__cur = 0x10084a957f0
(gdb)
I will share the info which i have, Pls suggest me how to proceed. I really do not know what info to give here. If any one want me to run any command and get memory print i can share.
(gdb) p &__tmp
$13 = (_STL::_List_node<int> **) 0x2b577b70e4b8
(gdb)
Registers, eax will have this wrong value
$13 = (_STL::_List_node<int> **) 0x2b577b70e4b8
(gdb) i r
rax 0x10084a957f0 1101737318384
rbx 0x2b5771e1fccb 47654572784843
rcx 0x2b576e1251d0 47654508843472
rdx 0x85 133
rsi 0x2b571729eee8 47653050773224
rdi 0x2b576debd408 47654506320904
rbp 0x2b577b70e4c0 0x2b577b70e4c0
rsp 0x2b577b70e4a0 0x2b577b70e4a0
r8 0x2b576d176480 47654492398720
r9 0x7bbe 31678
r10 0x2b5774f0a5e0 47654624077280
r11 0x2b57165c3f80 47653037293440
r12 0x2b577b716e68 47654733180520
r13 0x0 0
r14 0x2b57188221e0 47653073330656
r15 0x2b577b716e68 47654733180520
rip 0x2b5775455738 0x2b5775455738 <_STL::_List_base<int, _STL::allocator<int> >::clear()+40>
eflags 0x10206 [ PF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
mxcsr 0x1fa0 [ PE IM DM ZM OM UM PM ]
(gdb)
Some memory dump.
(gdb) x/20a 0x2b577b70e4b8 -20
0x2b577b70e4a4: 0x6debd40800002b57 0x84a957f000002b57
0x2b577b70e4b4: 0x84a957f000000100 0x7b70e4e000000100
0x2b577b70e4c4: 0x754557fb00002b57 0x7b70e55000002b57
0x2b577b70e4d4: 0x6debd40800002b57 0x7b70e50000002b57
0x2b577b70e4e4: 0x7545583100002b57 0x7b716e6800002b57
0x2b577b70e4f4: 0x6debd40800002b57 0x7b70e55000002b57
0x2b577b70e504: 0x75451de100002b57 0x6de161a000002b57
0x2b577b70e514: 0x100002b57 0x6debd40800000000
0x2b577b70e524: 0x6debd3c800002b57 0x2b57
0x2b577b70e534: 0x167f860800000000 0x71e1fccb00002b57

Minimal double type number in C aften which comupter start thinking that its zero

Sorry for my english. Can you tell me the smallest double type number after which the computer considers that the double type number equals zero?
Actual zero is zero. The result can become zero in different ways. A double has an value range of +/-10^+/-308 (roughly). A number smaller than the smallest number will be considered zero. Using #include <limits>, you can get numeric_limits<double>::denorm_min(), which is the smallest value that can be represented in a double.
But you can get "the effect of zero" in other ways. Say you have a fairly large number, 10 million, and you add (or subtract - read add as add or subtract in the rest of this paragraph) a very small number, say 1/10 million, then the addition will have no effect, because it is outside the actual value bits of the mantissa of the floating point number - that is, 53 bits in the case of double - then the effect will be the same as adding zero. In other words, even if you have a number that is not zero, using it to add to another number is not always going to change the other number.
See IEEE-754 on Wikipedia (other floating point formats do exist, but they are unusual).
You could try:
#include <limits>
std::numeric_limits<double>::denorm_min();
Doc for denormal (aka subnormal) numbers (here).
If this number is divided by e.g. by 2 the result is 0.
To check this values on a specific platform the following code can be used:
#include <iostream>
#include <limits>
using std::cout;
using std::endl;
int main() {
typedef double real;
union dbl {
real d;
unsigned char c[sizeof(d)];
dbl(const dbl &n = 0.0) : d(n.d) {}
dbl(double n) : d(n) {}
void pr(const char *txt = 0) const {
if (txt) cout << txt << ": ";
cout << d << ":";
for (int i = sizeof(d) -1; i >= 0; --i)
cout << std::hex << " " << (int)c[i];
cout << endl;
}
};
dbl n = 1.0;
for (; n.d > 0.0; n.d /= 2.0)
n.pr();
n.pr("zero");
n.d = std::numeric_limits<real>::min();
n.pr("min");
n.d = std::numeric_limits<real>::denorm_min();
n.pr("denorm_min");
}
Output on 32 bit linux (intel cpu) (doc about double format):
1: 3f f0 0 0 0 0 0 0
0.5: 3f e0 0 0 0 0 0 0
0.25: 3f d0 0 0 0 0 0 0
0.125: 3f c0 0 0 0 0 0 0
0.0625: 3f b0 0 0 0 0 0 0
...
8.9003e-308: 0 30 0 0 0 0 0 0
4.45015e-308: 0 20 0 0 0 0 0 0
2.22507e-308: 0 10 0 0 0 0 0 0
1.11254e-308: 0 8 0 0 0 0 0 0
5.56268e-309: 0 4 0 0 0 0 0 0
...
7.90505e-323: 0 0 0 0 0 0 0 10
3.95253e-323: 0 0 0 0 0 0 0 8
1.97626e-323: 0 0 0 0 0 0 0 4
9.88131e-324: 0 0 0 0 0 0 0 2
4.94066e-324: 0 0 0 0 0 0 0 1
zero: 0: 0 0 0 0 0 0 0 0
min: 2.22507e-308: 0 10 0 0 0 0 0 0
denorm_min: 4.94066e-324: 0 0 0 0 0 0 0 1
If real is defined as long double the output is:
1: 0 0 3f ff 80 0 0 0 0 0 0 0
0.5: 0 0 3f fe 80 0 0 0 0 0 0 0
0.25: 0 0 3f fd 80 0 0 0 0 0 0 0
0.125: 0 0 3f fc 80 0 0 0 0 0 0 0
0.0625: 0 0 3f fb 80 0 0 0 0 0 0 0
...
5.83232e-4950: 0 0 0 0 0 0 0 0 0 0 0 10
2.91616e-4950: 0 0 0 0 0 0 0 0 0 0 0 8
1.45808e-4950: 0 0 0 0 0 0 0 0 0 0 0 4
7.2904e-4951: 0 0 0 0 0 0 0 0 0 0 0 2
3.6452e-4951: 0 0 0 0 0 0 0 0 0 0 0 1
zero: 0: 0 0 0 0 0 0 0 0 0 0 0 0
min: 3.3621e-4932: 0 0 0 1 80 0 0 0 0 0 0 0
denorm_min: 3.6452e-4951: 0 0 0 0 0 0 0 0 0 0 0 1
Or for float:
1: 3f 80 0 0
0.5: 3f 0 0 0
0.25: 3e 80 0 0
0.125: 3e 0 0 0
0.0625: 3d 80 0 0
...
2.24208e-44: 0 0 0 10
1.12104e-44: 0 0 0 8
5.60519e-45: 0 0 0 4
2.8026e-45: 0 0 0 2
1.4013e-45: 0 0 0 1
zero: 0: 0 0 0 0
min: 1.17549e-38: 0 80 0 0
denorm_min: 1.4013e-45: 0 0 0 1
In the single-precision 32-bit and double-precision 64-bit format IEEE 754
The smallest positive normal value of double is 0x1.0p-1022 2.2250738585072014E-308.
The smallest positive denormal value of double is 0x0.0000000000001P-1022 4.9e-324.
The smallest positive normal value of float is 0x1.0p-126f 1.17549435E-38f.
The smallest positive denormal value of float is 0x0.000002P-126f 1.4e-45f.
Positive numbers smaller than above may result in 0, depending on the rounding-mode as Marc Glisse commented.
When you compare a double value that has been calculated, you should never check equality. You should check to see if is within a range. Not doing so would lead to the strong possibility that what you think is true is not so.
This is possibly a duplicate of this question.