Invent tool for renaming ELF object symbols

This commit is contained in:
Justine Tunney 2024-05-05 16:14:43 -07:00
parent 5fd7b07fac
commit 3bf95ae7ec
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
2 changed files with 370 additions and 58 deletions

View file

@ -289,15 +289,13 @@ static void RewriteTlsCodeAmd64(void) {
uint8_t *p;
Elf64_Shdr *shdr;
for (i = 0; i < elf->e_shnum; ++i) {
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i))) {
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i)))
Die("elf header overflow #1");
}
if (shdr->sh_type == SHT_PROGBITS && //
(shdr->sh_flags & SHF_ALLOC) && //
(shdr->sh_flags & SHF_EXECINSTR)) {
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
if (!(p = GetElfSectionAddress(elf, esize, shdr)))
Die("elf header overflow #2");
}
ChangeTlsFsToGs(p, shdr->sh_size);
}
}
@ -309,20 +307,16 @@ static void RewriteTlsCodeArm64(void) {
Elf64_Shdr *shdr;
uint32_t *p, *pe;
for (i = 0; i < elf->e_shnum; ++i) {
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i))) {
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i)))
Die("elf header overflow #1");
}
if (shdr->sh_type == SHT_PROGBITS && //
(shdr->sh_flags & SHF_ALLOC) && //
(shdr->sh_flags & SHF_EXECINSTR)) {
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
if (!(p = GetElfSectionAddress(elf, esize, shdr)))
Die("elf header overflow #2");
}
for (pe = p + shdr->sh_size / 4; p <= pe; ++p) {
if ((*p & -32) == MRS_TPIDR_EL0) {
for (pe = p + shdr->sh_size / 4; p <= pe; ++p)
if ((*p & -32) == MRS_TPIDR_EL0)
*p = MOV_REG(*p & 31, COSMO_TLS_REG);
}
}
}
}
}
@ -352,17 +346,14 @@ static void OptimizePatchableFunctionEntries(void) {
continue;
if (ELF64_ST_TYPE(syms[i].st_info) != STT_FUNC)
continue;
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, syms[i].st_shndx))) {
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, syms[i].st_shndx)))
Die("elf header overflow #3");
}
if (shdr->sh_type != SHT_PROGBITS)
continue;
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
if (!(p = GetElfSectionAddress(elf, esize, shdr)))
Die("elf section overflow");
}
if (ckd_sub(&sym_rva, syms[i].st_value, shdr->sh_addr)) {
if (ckd_sub(&sym_rva, syms[i].st_value, shdr->sh_addr))
Die("elf symbol beneath section");
}
if (sym_rva > esize - shdr->sh_offset || //
(p += sym_rva) >= (unsigned char *)elf + esize || //
syms[i].st_size >= esize - sym_rva) {
@ -403,17 +394,14 @@ static void RelinkZipFiles(void) {
recs = 0;
cdir = (stop = eocd) - (cdsize = ZIP_CDIR_SIZE(eocd));
for (cfile = cdir; cfile < stop; cfile += ZIP_CFILE_HDRSIZE(cfile)) {
if (++recs >= 65536) {
if (++recs >= 65536)
Die("too many zip central directory records");
}
if (cfile < base || //
cfile + kZipCfileHdrMinSize > xeof || //
cfile + ZIP_CFILE_HDRSIZE(cfile) > xeof) {
cfile + ZIP_CFILE_HDRSIZE(cfile) > xeof)
Die("zip central directory entry overflows image");
}
if (READ32LE(cfile) != kZipCfileHdrMagic) {
if (READ32LE(cfile) != kZipCfileHdrMagic)
Die("bad __zip_cdir_size or zip central directory corrupted");
}
if ((rela = ZIP_CFILE_OFFSET(cfile)) < 0) {
lfile = cfile + kZipCfileOffsetOffset + rela;
} else {
@ -421,33 +409,27 @@ static void RelinkZipFiles(void) {
}
if (lfile < base || //
lfile + kZipLfileHdrMinSize > xeof || //
lfile + ZIP_LFILE_SIZE(lfile) > xeof) {
lfile + ZIP_LFILE_SIZE(lfile) > xeof)
Die("zip local file overflows image");
}
if (READ32LE(lfile) != kZipLfileHdrMagic) {
if (READ32LE(lfile) != kZipLfileHdrMagic)
Die("zip central directory offset to local file corrupted");
}
if (rela < 0) {
if (rela < 0)
WRITE32LE(cfile + kZipCfileOffsetOffset, lfile - base);
}
}
// append new eocd record to program image
if (esize > INT_MAX - sizeof(foot) ||
(cdoffset = esize) > INT_MAX - sizeof(foot)) {
(cdoffset = esize) > INT_MAX - sizeof(foot))
Die("the time has come to adopt zip64");
}
bzero(foot, sizeof(foot));
WRITE32LE(foot, kZipCdirHdrMagic);
WRITE32LE(foot + kZipCdirSizeOffset, cdsize);
WRITE16LE(foot + kZipCdirRecordsOffset, recs);
WRITE32LE(foot + kZipCdirOffsetOffset, cdoffset);
WRITE16LE(foot + kZipCdirRecordsOnDiskOffset, recs);
if (pwrite(fildes, cdir, cdsize, esize) != cdsize) {
if (pwrite(fildes, cdir, cdsize, esize) != cdsize)
SysExit("cdir pwrite");
}
if (pwrite(fildes, foot, sizeof(foot), esize + cdsize) != sizeof(foot)) {
if (pwrite(fildes, foot, sizeof(foot), esize + cdsize) != sizeof(foot))
SysExit("eocd pwrite");
}
eocd = foot;
}
@ -656,29 +638,22 @@ static void PurgeIfuncSections(void) {
}
static void FixupObject(void) {
if ((fildes = open(epath, mode)) == -1) {
if ((fildes = open(epath, mode)) == -1)
SysExit("open");
}
if ((esize = lseek(fildes, 0, SEEK_END)) == -1) {
if ((esize = lseek(fildes, 0, SEEK_END)) == -1)
SysExit("lseek");
}
if (esize) {
elf = Malloc(esize);
if (pread(fildes, elf, esize, 0) != esize) {
if (pread(fildes, elf, esize, 0) != esize)
SysExit("pread");
}
if (!IsElf64Binary(elf, esize)) {
if (!IsElf64Binary(elf, esize))
Die("not an elf64 binary");
}
if (!(syms = GetElfSymbols(elf, esize, SHT_SYMTAB, &symcount))) {
if (!(syms = GetElfSymbols(elf, esize, SHT_SYMTAB, &symcount)))
Die("missing elf symbol table");
}
if (!(secstrs = GetElfSectionNameStringTable(elf, esize))) {
if (!(secstrs = GetElfSectionNameStringTable(elf, esize)))
Die("missing elf section string table");
}
if (!(symstrs = GetElfStringTable(elf, esize, ".strtab"))) {
if (!(symstrs = GetElfStringTable(elf, esize, ".strtab")))
Die("missing elf symbol string table");
}
CheckPrivilegedCrossReferences();
if (mode == O_RDWR) {
if (elf->e_machine == EM_NEXGEN32E) {
@ -687,29 +662,25 @@ static void FixupObject(void) {
GenerateIfuncInit();
} else if (elf->e_machine == EM_AARCH64) {
RewriteTlsCodeArm64();
if (elf->e_type != ET_REL) {
if (elf->e_type != ET_REL)
UseFreebsdOsAbi();
}
}
if (elf->e_type != ET_REL) {
PurgeIfuncSections();
RelinkZipFiles();
}
if (pwrite(fildes, elf, esize, 0) != esize) {
if (pwrite(fildes, elf, esize, 0) != esize)
SysExit("pwrite");
}
}
}
if (close(fildes)) {
if (close(fildes))
SysExit("close");
}
}
int main(int argc, char *argv[]) {
int i;
if (!IsOptimized()) {
if (!IsOptimized())
ShowCrashReports();
}
GetOpts(argc, argv);
for (i = optind; i < argc; ++i) {
epath = argv[i];