static inline bool do_check32 (size_t i, const Elf32_auxv_t (*a32)[], uint_fast8_t *elfdata) { /* The AUXV pointer might not even be naturally aligned for 32-bit data, because note payloads in a core file are not aligned. */ uint32_t type = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_type); uint32_t val = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_un.a_val); if (type == BE32 (PROBE_TYPE) && val == BE32 (PROBE_VAL32)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE32 (PROBE_TYPE) && val == LE32 (PROBE_VAL32)) { *elfdata = ELFDATA2LSB; return true; } return false; }
static int get_offsets (Dwarf *dbg) { size_t allocated = 0; size_t cnt = 0; struct pubnames_s *mem = NULL; const size_t entsize = sizeof (struct pubnames_s); unsigned char *const startp = dbg->sectiondata[IDX_debug_pubnames]->d_buf; unsigned char *readp = startp; unsigned char *endp = readp + dbg->sectiondata[IDX_debug_pubnames]->d_size; while (readp + 14 < endp) { /* If necessary, allocate more entries. */ if (cnt >= allocated) { allocated = MAX (10, 2 * allocated); struct pubnames_s *newmem = (struct pubnames_s *) realloc (mem, allocated * entsize); if (newmem == NULL) { __libdw_seterrno (DWARF_E_NOMEM); err_return: free (mem); return -1; } mem = newmem; } /* Read the set header. */ int len_bytes = 4; Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp); if (len == DWARF3_LENGTH_64_BIT) { len = read_8ubyte_unaligned_inc (dbg, readp); len_bytes = 8; } else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE)) { invalid_dwarf: __libdw_seterrno (DWARF_E_INVALID_DWARF); goto err_return; } /* Now we know the offset of the first offset/name pair. */ mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp; mem[cnt].address_len = len_bytes; if (mem[cnt].set_start >= dbg->sectiondata[IDX_debug_pubnames]->d_size) /* Something wrong, the first entry is beyond the end of the section. */ break; /* Read the version. It better be two for now. */ uint16_t version = read_2ubyte_unaligned (dbg, readp); if (unlikely (version != 2)) { __libdw_seterrno (DWARF_E_INVALID_VERSION); goto err_return; } /* Get the CU offset. */ if (len_bytes == 4) mem[cnt].cu_offset = read_4ubyte_unaligned (dbg, readp + 2); else mem[cnt].cu_offset = read_8ubyte_unaligned (dbg, readp + 2); /* Determine the size of the CU header. */ if (unlikely (dbg->sectiondata[IDX_debug_info] == NULL || dbg->sectiondata[IDX_debug_info]->d_buf == NULL || (mem[cnt].cu_offset + 3 >= dbg->sectiondata[IDX_debug_info]->d_size))) goto invalid_dwarf; unsigned char *infop = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf + mem[cnt].cu_offset); if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT) mem[cnt].cu_header_size = 23; else mem[cnt].cu_header_size = 11; ++cnt; /* Advance to the next set. */ readp += len; } if (mem == NULL) { __libdw_seterrno (DWARF_E_NO_ENTRY); return -1; } dbg->pubnames_sets = (struct pubnames_s *) realloc (mem, cnt * entsize); dbg->pubnames_nsets = cnt; return 0; }
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; }