llvm.org GIT mirror llvm / 68a3deb
llvm-readobj: Add support for reading relocations in the Android packed format. This is in preparation for testing lld's upcoming relocation packing feature (D39152). I have verified that this implementation correctly unpacks the relocations from a Chromium DSO built with gold and the Android relocation packer for ARM32 and ARM64. Differential Revision: https://reviews.llvm.org/D39272 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316543 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 1 year, 11 months ago
14 changed file(s) with 338 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
729729 SHT_GROUP = 17, // Section group.
730730 SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries.
731731 SHT_LOOS = 0x60000000, // Lowest operating system-specific type.
732 // Android packed relocation section types.
733 // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#37
734 SHT_ANDROID_REL = 0x60000001,
735 SHT_ANDROID_RELA = 0x60000002,
732736 SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table.
733737 SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes.
734738 SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table.
11641168 DT_HIOS = 0x6FFFFFFF, // End of environment specific tags.
11651169 DT_LOPROC = 0x70000000, // Start of processor specific tags.
11661170 DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags.
1171
1172 // Android packed relocation section tags.
1173 // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#31
1174 DT_ANDROID_REL = 0x6000000F,
1175 DT_ANDROID_RELSZ = 0x60000010,
1176 DT_ANDROID_RELA = 0x60000011,
1177 DT_ANDROID_RELASZ = 0x60000012,
11671178
11681179 DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table.
11691180 DT_TLSDESC_PLT =
13861397 GNU_ABI_TAG_NACL = 6,
13871398 };
13881399
1400 // Android packed relocation group flags.
1401 enum {
1402 RELOCATION_GROUPED_BY_INFO_FLAG = 1,
1403 RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2,
1404 RELOCATION_GROUPED_BY_ADDEND_FLAG = 4,
1405 RELOCATION_GROUP_HAS_ADDEND_FLAG = 8,
1406 };
1407
13891408 // Compressed section header for ELF32.
13901409 struct Elf32_Chdr {
13911410 Elf32_Word ch_type;
141141 return getSectionContentsAsArray(Sec);
142142 }
143143
144 Expected> android_relas(const Elf_Shdr *Sec) const;
145
144146 /// \brief Iterate over program header table.
145147 Expected program_headers() const {
146148 if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
88
99 #include "llvm/Object/ELF.h"
1010 #include "llvm/BinaryFormat/ELF.h"
11 #include "llvm/Support/LEB128.h"
1112
1213 using namespace llvm;
1314 using namespace object;
209210 return "Unknown";
210211 }
211212 }
213
214 template
215 Expected>
216 ELFFile::android_relas(const Elf_Shdr *Sec) const {
217 // This function reads relocations in Android's packed relocation format,
218 // which is based on SLEB128 and delta encoding.
219 Expected> ContentsOrErr = getSectionContents(Sec);
220 if (!ContentsOrErr)
221 return ContentsOrErr.takeError();
222 const uint8_t *Cur = ContentsOrErr->begin();
223 const uint8_t *End = ContentsOrErr->end();
224 if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
225 Cur[2] != 'S' || Cur[3] != '2')
226 return createError("invalid packed relocation header");
227 Cur += 4;
228
229 const char *ErrStr = nullptr;
230 auto ReadSLEB = [&]() -> int64_t {
231 if (ErrStr)
232 return 0;
233 unsigned Len;
234 int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
235 Cur += Len;
236 return Result;
237 };
238
239 uint64_t NumRelocs = ReadSLEB();
240 uint64_t Offset = ReadSLEB();
241 uint64_t Addend = 0;
242
243 if (ErrStr)
244 return createError(ErrStr);
245
246 std::vector Relocs;
247 Relocs.reserve(NumRelocs);
248 while (NumRelocs) {
249 uint64_t NumRelocsInGroup = ReadSLEB();
250 if (NumRelocsInGroup > NumRelocs)
251 return createError("relocation group unexpectedly large");
252 NumRelocs -= NumRelocsInGroup;
253
254 uint64_t GroupFlags = ReadSLEB();
255 bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
256 bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
257 bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
258 bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;
259
260 uint64_t GroupOffsetDelta;
261 if (GroupedByOffsetDelta)
262 GroupOffsetDelta = ReadSLEB();
263
264 uint64_t GroupRInfo;
265 if (GroupedByInfo)
266 GroupRInfo = ReadSLEB();
267
268 if (GroupedByAddend && GroupHasAddend)
269 Addend += ReadSLEB();
270
271 for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
272 Elf_Rela R;
273 Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
274 R.r_offset = Offset;
275 R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
276
277 if (GroupHasAddend) {
278 if (!GroupedByAddend)
279 Addend += ReadSLEB();
280 R.r_addend = Addend;
281 } else {
282 R.r_addend = 0;
283 }
284
285 Relocs.push_back(R);
286
287 if (ErrStr)
288 return createError(ErrStr);
289 }
290
291 if (ErrStr)
292 return createError(ErrStr);
293 }
294
295 return Relocs;
296 }
297
298 template class llvm::object::ELFFile;
299 template class llvm::object::ELFFile;
300 template class llvm::object::ELFFile;
301 template class llvm::object::ELFFile;
404404 ECase(SHT_GROUP);
405405 ECase(SHT_SYMTAB_SHNDX);
406406 ECase(SHT_LOOS);
407 ECase(SHT_ANDROID_REL);
408 ECase(SHT_ANDROID_RELA);
407409 ECase(SHT_LLVM_ODRTAB);
408410 ECase(SHT_GNU_ATTRIBUTES);
409411 ECase(SHT_GNU_HASH);
0 .ascii "APS2"
1 .sleb128 8 // Number of relocations
2 .sleb128 4096 // Initial offset
3
4 .sleb128 2 // Number of relocations in group
5 .sleb128 1 // RELOCATION_GROUPED_BY_INFO_FLAG
6 .sleb128 8 // R_X86_RELATIVE
7
8 .sleb128 256 // Reloc 1: r_offset delta
9 .sleb128 128 // Reloc 2: r_offset delta
10
11 .sleb128 2 // Number of relocations in group
12 .sleb128 2 // RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG
13 .sleb128 8 // offset delta
14
15 .sleb128 (1 << 32) | 1 // R_X86_64_64 (sym index 1)
16 .sleb128 (2 << 32) | 1 // R_X86_64_64 (sym index 2)
17
18 .sleb128 2 // Number of relocations in group
19 .sleb128 8 // RELOCATION_GROUP_HAS_ADDEND_FLAG
20
21 .sleb128 1 // offset delta
22 .sleb128 (1 << 32) | 1 // R_X86_64_64 (sym index 1)
23 .sleb128 8 // addend delta
24
25 .sleb128 2 // offset delta
26 .sleb128 (2 << 32) | 1 // R_X86_64_64 (sym index 2)
27 .sleb128 4 // addend delta
28
29 .sleb128 2 // Number of relocations in group
30 .sleb128 12 // RELOCATION_GROUP_HAS_ADDEND_FLAG | RELOCATION_GROUPED_BY_ADDEND_FLAG
31 .sleb128 -2 // addend delta
32
33 .sleb128 4 // offset delta
34 .sleb128 (1 << 32) | 1 // R_X86_64_64 (sym index 1)
35 .sleb128 8 // offset delta
36 .sleb128 (2 << 32) | 1 // R_X86_64_64 (sym index 2)
0 .ascii "APS2"
1 .sleb128 10 // Number of relocations
2 .sleb128 4096 // Initial offset
3
4 .sleb128 2 // Number of relocations in group
5 .sleb128 2 // RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG
6 .sleb128 8 // offset delta
7
8 .sleb128 (1 << 8) | 1 // R_386_32 (sym index 1)
9 .sleb128 (2 << 8) | 3 // R_386_GOT32 (sym index 2)
10
11 .sleb128 8 // Number of relocations in group
12 .sleb128 3 // RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | RELOCATION_GROUPED_BY_INFO_FLAG
13 .sleb128 -4 // offset delta
14 .sleb128 8 // R_386_RELATIVE
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -relocations - | FileCheck %s
1
2 // CHECK: Relocations [
3 // CHECK-NEXT: Section (3) .rela.dyn {
4 // CHECK-NEXT: }
5 // CHECK-NEXT: ]
6
7 .section .rela.dyn, "a", @0x60000001
8 .ascii "APS2"
9 .sleb128 0
10 .sleb128 0
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | not llvm-readobj -relocations - 2>&1 | FileCheck %s
1
2 // CHECK: Error reading file: invalid packed relocation header
3
4 .section .rela.dyn, "a", @0x60000001
5 .ascii "APS9"
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | not llvm-readobj -relocations - 2>&1 | FileCheck %s
1
2 // CHECK: Error reading file: malformed sleb128, extends past end
3
4 .section .rela.dyn, "a", @0x60000001
5 .ascii "APS2"
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | not llvm-readobj -relocations - 2>&1 | FileCheck %s
1
2 // CHECK: Error reading file: malformed sleb128, extends past end
3
4 .section .rela.dyn, "a", @0x60000001
5 .ascii "APS2"
6 .sleb128 4 // Number of relocations
7 .sleb128 0 // Initial offset
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | not llvm-readobj -relocations - 2>&1 | FileCheck %s
1
2 // CHECK: Error reading file: malformed sleb128, extends past end
3
4 .section .rela.dyn, "a", @0x60000001
5 .ascii "APS2"
6 .sleb128 4 // Number of relocations
7 .sleb128 0 // Initial offset
8
9 .sleb128 2 // Number of relocations in group
10 .sleb128 2 // RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG
11 .sleb128 8 // offset delta
0 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | not llvm-readobj -relocations - 2>&1 | FileCheck %s
1
2 // CHECK: Error reading file: relocation group unexpectedly large
3
4 .section .rela.dyn, "a", @0x60000001
5 .ascii "APS2"
6 .sleb128 4 // Number of relocations
7 .sleb128 0 // Initial offset
8
9 .sleb128 5 // Number of relocations in group
10 .sleb128 2 // RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG
11 .sleb128 8 // offset delta
0 # The binary blobs in this file were created like this:
1 # llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu Inputs/elf-packed-relocs1.s -o - | obj2yaml | grep Content:
2
3 # RUN: yaml2obj -docnum 1 %s | llvm-readobj -elf-output-style=LLVM -relocations - | FileCheck --check-prefix=LLVM1 %s
4 # LLVM1: Section (1) .rela.dyn {
5 # LLVM1-NEXT: 0x1100 R_X86_64_RELATIVE - 0x0
6 # LLVM1-NEXT: 0x1180 R_X86_64_RELATIVE - 0x0
7 # LLVM1-NEXT: 0x1188 R_X86_64_64 sym1 0x0
8 # LLVM1-NEXT: 0x1190 R_X86_64_64 sym2 0x0
9 # LLVM1-NEXT: 0x1191 R_X86_64_64 sym1 0x8
10 # LLVM1-NEXT: 0x1193 R_X86_64_64 sym2 0xC
11 # LLVM1-NEXT: 0x1197 R_X86_64_64 sym1 0xA
12 # LLVM1-NEXT: 0x119F R_X86_64_64 sym2 0xA
13 # LLVM1-NEXT: }
14
15 # RUN: yaml2obj -docnum 1 %s | llvm-readobj -elf-output-style=GNU -relocations - | FileCheck --check-prefix=GNU1 %s
16 # GNU1: 0000000000001100 0000000000000008 R_X86_64_RELATIVE 0
17 # GNU1-NEXT: 0000000000001180 0000000000000008 R_X86_64_RELATIVE 0
18 # GNU1-NEXT: 0000000000001188 0000000100000001 R_X86_64_64 0000000000000000 sym1 + 0
19 # GNU1-NEXT: 0000000000001190 0000000200000001 R_X86_64_64 0000000000000000 sym2 + 0
20 # GNU1-NEXT: 0000000000001191 0000000100000001 R_X86_64_64 0000000000000000 sym1 + 8
21 # GNU1-NEXT: 0000000000001193 0000000200000001 R_X86_64_64 0000000000000000 sym2 + c
22 # GNU1-NEXT: 0000000000001197 0000000100000001 R_X86_64_64 0000000000000000 sym1 + a
23 # GNU1-NEXT: 000000000000119f 0000000200000001 R_X86_64_64 0000000000000000 sym2 + a
24
25 # elf-packed-relocs1.s
26 --- !ELF
27 FileHeader:
28 Class: ELFCLASS64
29 Data: ELFDATA2LSB
30 Type: ET_DYN
31 Machine: EM_X86_64
32 Entry: 0x0000000000001000
33 Sections:
34 - Name: .rela.dyn
35 Type: SHT_ANDROID_RELA
36 Flags: [ SHF_ALLOC ]
37 Address: 0x00000000000001C8
38 Link: .symtab
39 AddressAlign: 0x0000000000000001
40 Content: 41505332088020020108800280010202088180808010818080802002080181808080100802818080802004020C7E048180808010088180808020
41 Symbols:
42 Global:
43 - Name: sym1
44 - Name: sym2
45 ...
46
47 # RUN: yaml2obj -docnum 2 %s | llvm-readobj -elf-output-style=LLVM -relocations - | FileCheck --check-prefix=LLVM2 %s
48 # LLVM2: Section (1) .rel.dyn {
49 # LLVM2-NEXT: 0x1008 R_386_32 sym1 0x0
50 # LLVM2-NEXT: 0x1010 R_386_GOT32 sym2 0x0
51 # LLVM2-NEXT: 0x100C R_386_RELATIVE - 0x0
52 # LLVM2-NEXT: 0x1008 R_386_RELATIVE - 0x0
53 # LLVM2-NEXT: 0x1004 R_386_RELATIVE - 0x0
54 # LLVM2-NEXT: 0x1000 R_386_RELATIVE - 0x0
55 # LLVM2-NEXT: 0xFFC R_386_RELATIVE - 0x0
56 # LLVM2-NEXT: 0xFF8 R_386_RELATIVE - 0x0
57 # LLVM2-NEXT: 0xFF4 R_386_RELATIVE - 0x0
58 # LLVM2-NEXT: 0xFF0 R_386_RELATIVE - 0x0
59 # LLVM2-NEXT: }
60
61 # RUN: yaml2obj -docnum 2 %s | llvm-readobj -elf-output-style=GNU -relocations - | FileCheck --check-prefix=GNU2 %s
62 # GNU2: 00001008 00000101 R_386_32 00000000 sym1
63 # GNU2-NEXT: 00001010 00000203 R_386_GOT32 00000000 sym2
64 # GNU2-NEXT: 0000100c 00000008 R_386_RELATIVE
65 # GNU2-NEXT: 00001008 00000008 R_386_RELATIVE
66 # GNU2-NEXT: 00001004 00000008 R_386_RELATIVE
67 # GNU2-NEXT: 00001000 00000008 R_386_RELATIVE
68 # GNU2-NEXT: 00000ffc 00000008 R_386_RELATIVE
69 # GNU2-NEXT: 00000ff8 00000008 R_386_RELATIVE
70 # GNU2-NEXT: 00000ff4 00000008 R_386_RELATIVE
71 # GNU2-NEXT: 00000ff0 00000008 R_386_RELATIVE
72
73 # elf-packed-relocs2.s
74 --- !ELF
75 FileHeader:
76 Class: ELFCLASS32
77 Data: ELFDATA2LSB
78 Type: ET_DYN
79 Machine: EM_386
80 Entry: 0x0000000000001000
81 Sections:
82 - Name: .rel.dyn
83 Type: SHT_ANDROID_REL
84 Flags: [ SHF_ALLOC ]
85 Address: 0x00000000000001C8
86 Link: .symtab
87 AddressAlign: 0x0000000000000001
88 Content: 415053320A80200202088102830408037C08
89 Symbols:
90 Global:
91 - Name: sym1
92 - Name: sym2
93 ...
25902590 template void GNUStyle::printRelocations(const ELFO *Obj) {
25912591 bool HasRelocSections = false;
25922592 for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
2593 if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
2593 if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
2594 Sec.sh_type != ELF::SHT_ANDROID_REL &&
2595 Sec.sh_type != ELF::SHT_ANDROID_RELA)
25942596 continue;
25952597 HasRelocSections = true;
25962598 StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
25992601 OS << "\nRelocation section '" << Name << "' at offset 0x"
26002602 << to_hexString(Offset, false) << " contains " << Entries
26012603 << " entries:\n";
2602 printRelocHeader(OS, ELFT::Is64Bits, (Sec.sh_type == ELF::SHT_RELA));
2604 printRelocHeader(OS, ELFT::Is64Bits,
2605 Sec.sh_type == ELF::SHT_RELA ||
2606 Sec.sh_type == ELF::SHT_ANDROID_RELA);
26032607 const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
2604 if (Sec.sh_type == ELF::SHT_REL) {
2608 switch (Sec.sh_type) {
2609 case ELF::SHT_REL:
26052610 for (const auto &R : unwrapOrError(Obj->rels(&Sec))) {
26062611 Elf_Rela Rela;
26072612 Rela.r_offset = R.r_offset;
26092614 Rela.r_addend = 0;
26102615 printRelocation(Obj, SymTab, Rela, false);
26112616 }
2612 } else {
2617 break;
2618 case ELF::SHT_RELA:
26132619 for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
26142620 printRelocation(Obj, SymTab, R, true);
2621 break;
2622 case ELF::SHT_ANDROID_REL:
2623 case ELF::SHT_ANDROID_RELA:
2624 for (const auto &R : unwrapOrError(Obj->android_relas(&Sec)))
2625 printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA);
2626 break;
26152627 }
26162628 }
26172629 if (!HasRelocSections)
36493661 for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
36503662 ++SectionNumber;
36513663
3652 if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
3664 if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
3665 Sec.sh_type != ELF::SHT_ANDROID_REL &&
3666 Sec.sh_type != ELF::SHT_ANDROID_RELA)
36533667 continue;
36543668
36553669 StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
36803694 break;
36813695 case ELF::SHT_RELA:
36823696 for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
3697 printRelocation(Obj, R, SymTab);
3698 break;
3699 case ELF::SHT_ANDROID_REL:
3700 case ELF::SHT_ANDROID_RELA:
3701 for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
36833702 printRelocation(Obj, R, SymTab);
36843703 break;
36853704 }