static inline bool do_check64 (size_t i, const Elf64_auxv_t (*a64)[], uint_fast8_t *elfdata) { /* The AUXV pointer might not even be naturally aligned for 64-bit data, because note payloads in a core file are not aligned. */ uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type); uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val); if (type == BE64 (PROBE_TYPE) && val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE64 (PROBE_TYPE) && val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; }
/* Examine an auxv data block and determine its format. Return true iff we figured it out. */ static bool auxv_format_probe (const void *auxv, size_t size, uint_fast8_t *elfclass, uint_fast8_t *elfdata) { const union { char buf[size]; Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; } *u = auxv; inline bool check64 (size_t i) { /* The AUXV pointer might not even be naturally aligned for 64-bit data, because note payloads in a core file are not aligned. */ uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type); uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val); if (type == BE64 (PROBE_TYPE) && val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE64 (PROBE_TYPE) && val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; }
static int report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, Dwfl *dwfl, GElf_Addr r_debug_vaddr, Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg, struct r_debug_info *r_debug_info) { /* Skip r_version, to aligned r_map field. */ GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); void *buffer = NULL; size_t buffer_available = 0; inline int release_buffer (int result) { if (buffer != NULL) (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, memory_callback_arg); return result; } GElf_Addr addrs[4]; inline bool read_addrs (GElf_Addr vaddr, size_t n) { size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ /* Read a new buffer if the old one doesn't cover these words. */ if (buffer == NULL || vaddr < read_vaddr || vaddr - read_vaddr + nb > buffer_available) { release_buffer (0); read_vaddr = vaddr; int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); if (unlikely (segndx < 0) || unlikely (! (*memory_callback) (dwfl, segndx, &buffer, &buffer_available, vaddr, nb, memory_callback_arg))) return true; } Elf32_Addr (*a32)[n] = vaddr - read_vaddr + buffer; Elf64_Addr (*a64)[n] = (void *) a32; if (elfclass == ELFCLASS32) { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i])); else for (size_t i = 0; i < n; ++i) addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i])); } else { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i])); else for (size_t i = 0; i < n; ++i) addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i])); } return false; }