Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/bloaty.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ inline void ReadDWARFCompileUnits(const dwarf::File& file, const DualMap& map,
}
void ReadDWARFInlines(const dwarf::File& file, RangeSink* sink,
bool include_line);
void ReadEhFrame(std::string_view contents, RangeSink* sink);
void ReadEhFrameHdr(std::string_view contents, RangeSink* sink);
void ReadEhFrame(std::string_view contents, RangeSink* sink, bool is_64bit);
void ReadEhFrameHdr(std::string_view contents, RangeSink* sink, bool is_64bit);

// Demangle C++ symbols according to the Itanium ABI. The |source| argument
// controls what demangling mode we are using.
Expand Down
13 changes: 9 additions & 4 deletions src/dwarf_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,10 +674,15 @@ enum PointerEncoding {
DW_EH_PE_udata2 = 0x02,
DW_EH_PE_udata4 = 0x03,
DW_EH_PE_udata8 = 0x04,
DW_EH_PE_sleb128 = 0x09,
DW_EH_PE_sdata2 = 0x0A,
DW_EH_PE_sdata4 = 0x0B,
DW_EH_PE_sdata8 = 0x0C,

// This acts as a flag.
DW_EH_PE_signed = 0x08,

DW_EH_PE_sabsptr = DW_EH_PE_absptr | DW_EH_PE_signed,
DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed,
DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed,
DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed,
DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed,
DW_EH_PE_FORMAT_MASK = 0x0f,

DW_EH_PE_pcrel = 0x10,
Expand Down
29 changes: 17 additions & 12 deletions src/eh_frame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ uint64_t ReadEncodedPointer(uint8_t encoding, bool is_64bit, string_view* data,
value = ReadFixed<uint32_t>(data);
}
break;
case DW_EH_PE_sabsptr:
if (is_64bit) {
value = ReadFixed<int64_t>(data);
} else {
value = ReadFixed<int32_t>(data);
}
break;
case DW_EH_PE_uleb128:
value = dwarf::ReadLEB128<uint64_t>(data);
break;
Expand Down Expand Up @@ -124,7 +131,7 @@ uint64_t ReadEncodedPointer(uint8_t encoding, bool is_64bit, string_view* data,
// https://github.com/llvm-mirror/libunwind/blob/master/src/DwarfParser.hpp
// * libgcc
// https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2-fde.c
void ReadEhFrame(string_view data, RangeSink* sink) {
void ReadEhFrame(string_view data, RangeSink* sink, bool is_64bit) {
string_view remaining = data;

struct CIEInfo {
Expand Down Expand Up @@ -187,7 +194,7 @@ void ReadEhFrame(string_view data, RangeSink* sink) {
case 'P': {
uint8_t encoding = ReadFixed<uint8_t>(&entry);
cie_info.personality_function =
ReadEncodedPointer(encoding, true, &entry, nullptr, sink);
ReadEncodedPointer(encoding, is_64bit, &entry, nullptr, sink);
break;
}
default:
Expand All @@ -201,14 +208,13 @@ void ReadEhFrame(string_view data, RangeSink* sink) {
THROW("Couldn't find CIE for FDE");
}
const CIEInfo& cie_info = iter->second;
// TODO(haberman): don't hard-code 64-bit.
uint64_t address = ReadEncodedPointer(cie_info.fde_encoding, true, &entry,
uint64_t address = ReadEncodedPointer(cie_info.fde_encoding, is_64bit, &entry,
nullptr, sink);
// TODO(haberman); Technically the FDE addresses could span a
// function/compilation unit? They can certainly span inlines.
/*
uint64_t length =
ReadEncodedPointer(cie_info.fde_encoding & 0xf, true, &entry, sink);
ReadEncodedPointer(cie_info.fde_encoding & 0xf, is_64bit, &entry, sink);
(void)length;

if (cie_info.has_augmentation_length) {
Expand All @@ -217,7 +223,7 @@ void ReadEhFrame(string_view data, RangeSink* sink) {
}

uint64_t lsda =
ReadEncodedPointer(cie_info.lsda_encoding, true, &entry, sink);
ReadEncodedPointer(cie_info.lsda_encoding, is_64bit, &entry, sink);
if (lsda) {
}
*/
Expand All @@ -229,7 +235,7 @@ void ReadEhFrame(string_view data, RangeSink* sink) {

// See documentation here:
// http://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html#EHFRAME
void ReadEhFrameHdr(string_view data, RangeSink* sink) {
void ReadEhFrameHdr(string_view data, RangeSink* sink, bool is_64bit) {
const char* base = data.data();
uint8_t version = ReadFixed<uint8_t>(&data);
uint8_t eh_frame_ptr_enc = ReadFixed<uint8_t>(&data);
Expand All @@ -240,12 +246,11 @@ void ReadEhFrameHdr(string_view data, RangeSink* sink) {
THROWF("Unknown eh_frame_hdr version: $0", version);
}

// TODO(haberman): don't hard-code 64-bit.
uint64_t eh_frame_ptr =
ReadEncodedPointer(eh_frame_ptr_enc, true, &data, base, sink);
ReadEncodedPointer(eh_frame_ptr_enc, is_64bit, &data, base, sink);
(void)eh_frame_ptr;
uint64_t fde_count =
ReadEncodedPointer(fde_count_enc, true, &data, base, sink);
ReadEncodedPointer(fde_count_enc, is_64bit, &data, base, sink);

if (table_enc == DW_EH_PE_omit) {
return;
Expand All @@ -254,8 +259,8 @@ void ReadEhFrameHdr(string_view data, RangeSink* sink) {
for (uint64_t i = 0; i < fde_count; i++) {
string_view entry_data = data;
uint64_t initial_location =
ReadEncodedPointer(table_enc, true, &data, base, sink);
uint64_t fde_addr = ReadEncodedPointer(table_enc, true, &data, base, sink);
ReadEncodedPointer(table_enc, is_64bit, &data, base, sink);
uint64_t fde_addr = ReadEncodedPointer(table_enc, is_64bit, &data, base, sink);
entry_data.remove_suffix(data.size());
sink->AddFileRangeForVMAddr("dwarf_fde_table", initial_location,
entry_data);
Expand Down
4 changes: 2 additions & 2 deletions src/elf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1022,9 +1022,9 @@ static void ReadELFTables(const InputFile& file, RangeSink* sink) {
// fde entries from there). But these section names should be
// standard enough that this approach works also.
if (section.GetName() == ".eh_frame") {
ReadEhFrame(section.contents(), sink);
ReadEhFrame(section.contents(), sink, elf.is_64bit());
} else if (section.GetName() == ".eh_frame_hdr") {
ReadEhFrameHdr(section.contents(), sink);
ReadEhFrameHdr(section.contents(), sink, elf.is_64bit());
}
}
});
Expand Down
53 changes: 53 additions & 0 deletions tests/elf/sections/eh-frame-signed.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# RUN: %yaml2obj %s -o %t.o
# RUN: %bloaty -d symbols %t.o | %FileCheck %s

--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_386
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
Size: 0x100
- Name: .eh_frame
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
AddressAlign: 4
# CIE Details:
# 10000000 # Length (16 bytes)
# 00000000 # CIE ID (0)
# 01 # Version (1)
# 7A5200 # Augmentation String: "zR"
# 01 # Code Alignment Factor (1)
# 7C # Data Alignment Factor (-4)
# 08 # Return Address Register (8)
# 01 # Augmentation Data Length (1)
# 08 # Augmentation Data (FDE Encoding: DW_EH_PE_signed = 0x08)
# 000000 # Padding (DW_CFA_nop)
# FDE Details:
# 0C000000 # Length (12 bytes)
# 18000000 # CIE Pointer (offset 24 backwards from here -> points to CIE at 0)
# 00100000 # PC Begin (0x1000, encoded as DW_EH_PE_signed 32-bit)
# 00010000 # PC Range (0x100, assuming same encoding)
Content: 1000000000000000017A5200017C0801080000000C000000180000000010000000010000

Symbols:
- Name: foo
Type: STT_FUNC
Section: .text
Value: 0x1000
Size: 0x100

# CHECK: FILE SIZE VM SIZE
# CHECK-NEXT: -------------- --------------
# CHECK-NEXT: 41.7% 277 87.7% 256 foo
# CHECK-NEXT: 36.1% 240 0.0% 0 [ELF Section Headers]
# CHECK-NEXT: 7.8% 52 0.0% 0 [ELF Header]
# CHECK-NEXT: 6.5% 43 0.0% 0 [section .shstrtab]
# CHECK-NEXT: 5.4% 36 12.3% 36 [section .eh_frame]
# CHECK-NEXT: 2.4% 16 0.0% 0 [section .symtab]
# CHECK-NEXT: 100.0% 664 100.0% 292 TOTAL