elfhack crashes when library is larger than 4G
Categories
(Firefox Build System :: General, defect)
Tracking
(firefox97 fixed)
Tracking | Status | |
---|---|---|
firefox97 | --- | fixed |
People
(Reporter: stransky, Assigned: glandium)
References
Details
Attachments
(2 files)
Reporter | ||
Comment 1•6 years ago
|
||
Reporter | ||
Updated•6 years ago
|
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Comment 3•5 years ago
|
||
Hello.
I was working on a fix for this, but when gdb blew up while attempting to step into Elf::Elf() I gave up. So to reiterate a few things I posted in bug #1554428, this problem is due to using a 32-bit int for both ELF32 and ELF64 offsets, although ELF64 offsets are 64-bit. build/unix/elfhack/elfxx.h:284:
ElfSection *getSectionAt(unsigned int offset);
There are more places aside from this one, e.g., ElfLocation. Perhaps something else later treats this as signed, thus leading to the problem? Either way, I'm confident that building with -g3 can even get us over the 4GiB mark.
Additionally, the error handing and reporting is extremely poor in this code and should be improved. Aside from that, I recommend something like:
struct ELF64 {
typedef uint64_t offset_type;
typedef int64_t reloffset_type;
typedef uint32_t size_type;
... etc.
};
struct ELF32 {
typedef uint32_t offset_type;
typedef int32_t reloffset_type;
typedef uint32_t size_type;
... etc.
};
template<typename elfver>
class Elf {
... etc.
};
And then modify these types to something like:
template<typename elfver, typename T>
class ElfValue {
ElfSection<elfver> *section;
// Moving section into this class cleans up subclasses, at the expense of
// making a few objects slightly larger, but also shrinking the vtable.
public:
ElfValue::ElfValue(ElfSection<elfver> *section_ = NULL) : section(section_) {}
virtual T getValue() { return 0; }
virtual ElfSection<elfver> *getSection() { return section; }
};
...
template<typename elfver>
class ElfLocation: public ElfValue<elfver, elfver::offset_type> {
typename elfver::reloffset_type offset;
public:
enum position { ABSOLUTE, RELATIVE };
ElfLocation(): ElfValue(NULL), offset(0) {};
ElfLocation(ElfSection *section, typename elfver::reloffset_type off, enum position pos = RELATIVE);
ElfLocation(typename elfver::offset_type location, Elf *elf);
typename elfver::offset_type getValue();
};
template<typename elfver>
class ElfSize: public ElfValue<elfver, elfver::size_type> {
public:
ElfSize(ElfSection *s)<elfver>: ElfValue(s) {};
typename elfver::size_type getValue();
};
Etcetera. This will add code bloat as code for Elf<ELF32> and Elf<ELF64> will generate separate copies (unless elfhack is built for only one target), but icache efficiency shouldn't be a factor. This design will also better facilitate support for future versions of ELF files.
Comment 4•5 years ago
|
||
Correction, I forgot to remove the virtual
from ElfValue::ElfSection()
.
Assignee | ||
Comment 5•4 years ago
|
||
This only solves the easy half of the problem outlined in the bug,
leaving the other half for later.
iostream::tellg() actually returns streampos, which is able to support
files larger than 4GiB with libstdc++, but converting to an int
obviously truncated that, as well as transformed values between 2GiB and
4GiB into invalid negative numbers.
iostream::seekg() also takes a streampos, so storing the streampos as-is
is enough to address the problem with tellg()/seekg() sequences.
The other half of the problem involves elfhack converting 64-bits ELF
headers to 32-bits headers internally, which requires deeper changes.
This change however, is enough to support files up to 4GiB, which is
already a good first step.
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Comment 7•4 years ago
|
||
bugherder |
Comment 8•4 years ago
|
||
The leave-open keyword is there and there is no activity for 6 months.
:glandium, maybe it's time to close this bug?
Assignee | ||
Updated•4 years ago
|
Assignee | ||
Comment 9•3 years ago
|
||
Elfhack currently can't deal with files larger than 4GiB because it
translates all ELF data structures to the 32-bits variant, even for
64-bits ELF files. So if the original file has e.g. sections that start
after the 4GiB boundary, they can't be represented in memory.
Practically speaking, this is not causing problems, but has prevented a
working elfhack for aarch64 because e.g. some relocation types don't fit
in the 32-bits ELF representation.
Comment 10•3 years ago
|
||
Comment 11•3 years ago
|
||
bugherder |
Description
•