Skip to content

Commit adef21b

Browse files
committed
elf2rpl: add TLS Support.
1 parent b31b773 commit adef21b

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/common/elf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ enum SectionFlags : uint32_t // sh_flags
5555
SHF_WRITE = 0x1,
5656
SHF_ALLOC = 0x2,
5757
SHF_EXECINSTR = 0x4,
58+
SHF_TLS = 0x0400,
59+
SHF_RPL_TLS = 0x04000000,
5860
SHF_DEFLATED = 0x08000000,
5961
SHF_MASKPROC = 0xF0000000,
6062
};
@@ -197,6 +199,7 @@ enum RelocationType : uint32_t // r_info & 0xff
197199
enum RplFileInfoFlag : uint32_t
198200
{
199201
RPL_IS_RPX = 0x2,
202+
RPL_TLS = 0x8,
200203
};
201204

202205
static const unsigned HeaderMagic = 0x7f454c46;

src/elf2rpl/main.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <set>
1111
#include <string>
1212
#include <vector>
13+
#include <math.h>
1314
#include <zlib.h>
1415

1516
constexpr auto DeflateMinSectionSize = 0x18u;
@@ -116,6 +117,11 @@ readElf(ElfFile &file, const std::string &filename)
116117
section.header.flags |= elf::SHF_WRITE;
117118
}
118119

120+
if (section.header.flags & elf::SHF_TLS) {
121+
section.header.flags &= ~elf::SHF_TLS;
122+
section.header.flags |= elf::SHF_RPL_TLS;
123+
}
124+
119125
auto pos = in.tellg();
120126
in.seekg(static_cast<size_t>(section.header.offset));
121127
section.data.resize(section.header.size);
@@ -176,6 +182,12 @@ generateFileInfoSection(ElfFile &file,
176182
size = section->header.size;
177183
}
178184

185+
if (section->header.flags & elf::SHF_RPL_TLS) {
186+
info.flags |= elf::RPL_TLS;
187+
if ((1 << info.tlsAlignShift) < section->header.addralign)
188+
info.tlsAlignShift = (uint16_t)log2((float)section->header.addralign);
189+
}
190+
179191
if (section->header.addr >= CodeBaseAddress &&
180192
section->header.addr < DataBaseAddress) {
181193
auto val = section->header.addr + section->header.size - CodeBaseAddress;
@@ -362,6 +374,53 @@ fixRelocations(ElfFile &file)
362374
break;
363375
}
364376

377+
/*
378+
* Convert R_PPC_GOT_TLSGD16/R_PPC_TLSGD into R_PPC_DTPMOD32/R_PPC_DTPREL32
379+
*/
380+
case elf::R_PPC_TLSGD:
381+
case elf::R_PPC_GOT_TLSGD16: {
382+
uint32_t gotAddr = 0;
383+
bool gotFound = false;
384+
auto strTab = file.sections[symbolSection->header.link]->data.data();
385+
for (int j = 0; j < symbolSection->data.size() / sizeof(elf::Symbol); j++) {
386+
elf::Symbol symbol;
387+
getSymbol(*symbolSection, j, symbol);
388+
if (!strcmp(strTab + symbol.name, "_GLOBAL_OFFSET_TABLE_")) {
389+
gotFound = true;
390+
gotAddr = symbol.value;
391+
if (targetSection->name != file.sections[symbol.shndx]->name) {
392+
fmt::print("ERROR: \"_GLOBAL_OFFSET_TABLE_\" found in section \"{}\" instead of \"{}\", "
393+
"cannot fix a R_PPC_GOT_TLSGD16 relocation\n",
394+
file.sections[symbol.shndx]->name, targetSection->name);
395+
result = false;
396+
}
397+
break;
398+
}
399+
}
400+
401+
if (!gotFound) {
402+
fmt::print("ERROR: Could not find symbol \"_GLOBAL_OFFSET_TABLE_\" for fixing a R_PPC_GOT_TLSGD16 relocation\n");
403+
result = false;
404+
break;
405+
}
406+
407+
/* tls_index is stored in GOT as 8 bytes (DTPMOD32 + DTPREL32)
408+
* GOT_TLSGD16 points to the offset of tls_index in GOT
409+
* for R_PPC_TLSGD, the offset is in the previous instruction
410+
*/
411+
be_val<int16_t> *tlsIndexOffset = (be_val<int16_t> *)(targetSection->data.data() + offset - targetSection->header.addr);
412+
413+
if (type == elf::R_PPC_GOT_TLSGD16) {
414+
rels[i].info = (index << 8) | elf::R_PPC_DTPMOD32;
415+
rels[i].offset = gotAddr + *tlsIndexOffset;
416+
} else {
417+
tlsIndexOffset--;
418+
rels[i].info = (index << 8) | elf::R_PPC_DTPREL32;
419+
rels[i].offset = gotAddr + *tlsIndexOffset + 4;
420+
}
421+
break;
422+
}
423+
365424
default:
366425
// Only print error once per type
367426
if (!unsupportedTypes.count(type)) {

0 commit comments

Comments
 (0)