MachO no longer needs contiguous LC_SEGMENT (SourceForge bug 3308161)
This commit is contained in:
parent
f890f6bb09
commit
d442c58fd1
@ -85,6 +85,52 @@ fpad4(OutputFile *fo)
|
|||||||
return d + len;
|
return d + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackLinuxElf32::hemfix(Elf32_Phdr *phdr, unsigned n_phdr)
|
||||||
|
{
|
||||||
|
unsigned j;
|
||||||
|
for (j=0; j < n_phdr; ++phdr, ++j) {
|
||||||
|
unsigned const mask = -phdr->p_align;
|
||||||
|
if (PT_LOAD32==phdr->p_type) { /* first PT_LOAD */
|
||||||
|
if (~mask & phdr->p_vaddr
|
||||||
|
&& 0==(~mask & (phdr->p_vaddr - phdr->p_offset))) {
|
||||||
|
unsigned const hem = ~mask & phdr->p_offset;
|
||||||
|
phdr->p_offset -= hem;
|
||||||
|
phdr->p_vaddr -= hem;
|
||||||
|
if (phdr->p_paddr)
|
||||||
|
phdr->p_paddr -= hem;
|
||||||
|
phdr->p_filesz += hem;
|
||||||
|
phdr->p_memsz += hem;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackLinuxElf64::hemfix(Elf64_Phdr *phdr, unsigned n_phdr)
|
||||||
|
{
|
||||||
|
unsigned j;
|
||||||
|
for (j=0; j < n_phdr; ++phdr, ++j) {
|
||||||
|
unsigned const mask = -phdr->p_align;
|
||||||
|
if (PT_LOAD64==phdr->p_type) { /* first PT_LOAD */
|
||||||
|
if (~mask & phdr->p_vaddr
|
||||||
|
&& 0==(~mask & (phdr->p_vaddr - phdr->p_offset))) {
|
||||||
|
unsigned const hem = ~mask & phdr->p_offset;
|
||||||
|
phdr->p_offset -= hem;
|
||||||
|
phdr->p_vaddr -= hem;
|
||||||
|
if (phdr->p_paddr)
|
||||||
|
phdr->p_paddr -= hem;
|
||||||
|
phdr->p_filesz += hem;
|
||||||
|
phdr->p_memsz += hem;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PackLinuxElf32::checkEhdr(Elf32_Ehdr const *ehdr) const
|
PackLinuxElf32::checkEhdr(Elf32_Ehdr const *ehdr) const
|
||||||
{
|
{
|
||||||
@ -1240,7 +1286,8 @@ bool PackLinuxElf32::canPack()
|
|||||||
|
|
||||||
unsigned osabi0 = u.buf[Elf32_Ehdr::EI_OSABI];
|
unsigned osabi0 = u.buf[Elf32_Ehdr::EI_OSABI];
|
||||||
// The first PT_LOAD32 must cover the beginning of the file (0==p_offset).
|
// The first PT_LOAD32 must cover the beginning of the file (0==p_offset).
|
||||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *)(u.buf + e_phoff);
|
Elf32_Phdr *phdr = (Elf32_Phdr *)(u.buf + e_phoff);
|
||||||
|
hemfix(phdr, umin(14, e_phnum));
|
||||||
note_size = 0;
|
note_size = 0;
|
||||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||||
if (j >= 14) {
|
if (j >= 14) {
|
||||||
@ -1476,16 +1523,16 @@ PackLinuxElf64amd::canPack()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The first PT_LOAD64 must cover the beginning of the file (0==p_offset).
|
// The first PT_LOAD64 must cover the beginning of the file (0==p_offset).
|
||||||
Elf64_Phdr const *phdr = (Elf64_Phdr const *)(u.buf + (unsigned) e_phoff);
|
Elf64_Phdr *phdr = (Elf64_Phdr *)(u.buf + e_phoff);
|
||||||
|
hemfix(phdr, umin(14, e_phnum));
|
||||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||||
if (j >= 14)
|
if (j >= 14)
|
||||||
return false;
|
return false;
|
||||||
if (phdr->PT_LOAD64 == get_te32(&phdr->p_type)) {
|
if (phdr->PT_LOAD64 == get_te32(&phdr->p_type)) {
|
||||||
// Just avoid the "rewind" when unpacking?
|
if (phdr->p_offset != 0) {
|
||||||
//if (phdr->p_offset != 0) {
|
throwCantPack("invalid Phdr p_offset; try '--force-execve'");
|
||||||
// throwCantPack("invalid Phdr p_offset; try '--force-execve'");
|
return false;
|
||||||
// return false;
|
}
|
||||||
//}
|
|
||||||
load_va = get_te64(&phdr->p_vaddr);
|
load_va = get_te64(&phdr->p_vaddr);
|
||||||
exetype = 1;
|
exetype = 1;
|
||||||
break;
|
break;
|
||||||
@ -1974,6 +2021,7 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
phdri = new Elf32_Phdr[e_phnum];
|
phdri = new Elf32_Phdr[e_phnum];
|
||||||
fi->seek(e_phoff, SEEK_SET);
|
fi->seek(e_phoff, SEEK_SET);
|
||||||
fi->readx(phdri, sz_phdrs);
|
fi->readx(phdri, sz_phdrs);
|
||||||
|
hemfix(phdri, e_phnum);
|
||||||
|
|
||||||
// Remember all PT_NOTE, and find lg2_page from PT_LOAD.
|
// Remember all PT_NOTE, and find lg2_page from PT_LOAD.
|
||||||
Elf32_Phdr const *phdr = phdri;
|
Elf32_Phdr const *phdr = phdri;
|
||||||
@ -2163,6 +2211,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
phdri = new Elf64_Phdr[e_phnum];
|
phdri = new Elf64_Phdr[e_phnum];
|
||||||
fi->seek(e_phoff, SEEK_SET);
|
fi->seek(e_phoff, SEEK_SET);
|
||||||
fi->readx(phdri, sz_phdrs);
|
fi->readx(phdri, sz_phdrs);
|
||||||
|
hemfix(phdri, e_phnum);
|
||||||
|
|
||||||
Elf64_Phdr const *phdr = phdri;
|
Elf64_Phdr const *phdr = phdri;
|
||||||
note_size = 0;
|
note_size = 0;
|
||||||
|
|||||||
@ -101,6 +101,7 @@ public:
|
|||||||
PackLinuxElf32(InputFile *f);
|
PackLinuxElf32(InputFile *f);
|
||||||
virtual ~PackLinuxElf32();
|
virtual ~PackLinuxElf32();
|
||||||
protected:
|
protected:
|
||||||
|
void hemfix(Elf32_Phdr *phdr, unsigned n_phdr);
|
||||||
virtual int checkEhdr(Elf32_Ehdr const *ehdr) const;
|
virtual int checkEhdr(Elf32_Ehdr const *ehdr) const;
|
||||||
virtual bool canPack();
|
virtual bool canPack();
|
||||||
|
|
||||||
@ -225,6 +226,7 @@ public:
|
|||||||
/*virtual void buildLoader(const Filter *);*/
|
/*virtual void buildLoader(const Filter *);*/
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void hemfix(Elf64_Phdr *phdr, unsigned n_phdr);
|
||||||
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
|
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
|
||||||
|
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||||
|
|||||||
@ -1376,7 +1376,7 @@ bool PackMachBase<T>::canPack()
|
|||||||
// Put LC_SEGMENT together at the beginning, ascending by .vmaddr.
|
// Put LC_SEGMENT together at the beginning, ascending by .vmaddr.
|
||||||
qsort(msegcmd, ncmds, sizeof(*msegcmd), compare_segment_command);
|
qsort(msegcmd, ncmds, sizeof(*msegcmd), compare_segment_command);
|
||||||
|
|
||||||
// Check that LC_SEGMENTs form one contiguous chunk of the file.
|
// Check alignment of non-null LC_SEGMENT.
|
||||||
for (unsigned j= 0; j < ncmds; ++j) {
|
for (unsigned j= 0; j < ncmds; ++j) {
|
||||||
if (lc_seg==msegcmd[j].cmd) {
|
if (lc_seg==msegcmd[j].cmd) {
|
||||||
if (~PAGE_MASK & (msegcmd[j].fileoff | msegcmd[j].vmaddr)) {
|
if (~PAGE_MASK & (msegcmd[j].fileoff | msegcmd[j].vmaddr)) {
|
||||||
@ -1384,13 +1384,11 @@ bool PackMachBase<T>::canPack()
|
|||||||
}
|
}
|
||||||
if (msegcmd[j].vmsize==0)
|
if (msegcmd[j].vmsize==0)
|
||||||
break; // was sorted last
|
break; // was sorted last
|
||||||
if (0 < j) {
|
|
||||||
unsigned const sz = PAGE_MASK
|
// We used to check that LC_SEGMENTS were contiguous,
|
||||||
& (~PAGE_MASK + msegcmd[j-1].filesize);
|
// but apparently that is not needed anymore,
|
||||||
if ((sz + msegcmd[j-1].fileoff)!=msegcmd[j].fileoff) {
|
// and Google compilers generate strange layouts.
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++n_segment;
|
++n_segment;
|
||||||
sz_segment = msegcmd[j].filesize + msegcmd[j].fileoff - msegcmd[0].fileoff;
|
sz_segment = msegcmd[j].filesize + msegcmd[j].fileoff - msegcmd[0].fileoff;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user