
# HG changeset patch
# User Mike Hommey <mh+mozilla@glandium.org>
# Date 1688068580 0
# Node ID 51b78cf4881b07422c0c6e590e863b095257e9e1
# Parent  eef8bff2d6117cc88dcca9ab4718be0f5186924b
Bug 1840931 - More properly handle files > 4GB in elfhack. r=gsvelto

I'm pretty sure there are other theoretical problems in the code,
notably when a single section is larger than 4GB, but by the time
we reach that limit, bug 1839740 will have been fixed.

Differential Revision: https://phabricator.services.mozilla.com/D182447

diff --git a/build/unix/elfhack/elf.cpp b/build/unix/elfhack/elf.cpp
--- a/build/unix/elfhack/elf.cpp
+++ b/build/unix/elfhack/elf.cpp
@@ -344,17 +344,17 @@ ElfSection* Elf::getSection(int index) {
         break;
       default:
         sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
     }
   }
   return sections[index];
 }
 
-ElfSection* Elf::getSectionAt(unsigned int offset) {
+ElfSection* Elf::getSectionAt(Elf64_Off offset) {
   for (int i = 1; i < ehdr->e_shnum; i++) {
     ElfSection* section = getSection(i);
     if ((section != nullptr) && (section->getFlags() & SHF_ALLOC) &&
         !(section->getFlags() & SHF_TLS) && (offset >= section->getAddr()) &&
         (offset < section->getAddr() + section->getSize()))
       return section;
   }
   return nullptr;
@@ -529,38 +529,38 @@ ElfSection::ElfSection(Elf_Shdr& s, std:
   // Only SHT_REL/SHT_RELA sections use sh_info to store a section
   // number.
   if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
     info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : nullptr;
   else
     info.index = shdr.sh_info;
 }
 
-unsigned int ElfSection::getAddr() {
+Elf64_Addr ElfSection::getAddr() {
   if (shdr.sh_addr != (Elf64_Addr)-1) return shdr.sh_addr;
 
   // It should be safe to adjust sh_addr for all allocated sections that
   // are neither SHT_NOBITS nor SHT_PROGBITS
   if ((previous != nullptr) && isRelocatable()) {
     unsigned int addr = previous->getAddr();
     if (previous->getType() != SHT_NOBITS) addr += previous->getSize();
 
     if (addr & (getAddrAlign() - 1)) addr = (addr | (getAddrAlign() - 1)) + 1;
 
     return (shdr.sh_addr = addr);
   }
   return shdr.sh_addr;
 }
 
-unsigned int ElfSection::getOffset() {
+Elf64_Off ElfSection::getOffset() {
   if (shdr.sh_offset != (Elf64_Off)-1) return shdr.sh_offset;
 
   if (previous == nullptr) return (shdr.sh_offset = 0);
 
-  unsigned int offset = previous->getOffset();
+  Elf64_Off offset = previous->getOffset();
 
   ElfSegment* ptload = getSegmentByType(PT_LOAD);
   ElfSegment* prev_ptload = previous->getSegmentByType(PT_LOAD);
 
   if (ptload && (ptload == prev_ptload)) {
     offset += getAddr() - previous->getAddr();
     return (shdr.sh_offset = offset);
   }
diff --git a/build/unix/elfhack/elfhack.cpp b/build/unix/elfhack/elfhack.cpp
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -1255,18 +1255,18 @@ int do_relocation_section(Elf* elf, unsi
         "Expected to find an .eh_frame section adjacent to .eh_frame_hdr");
   }
   if (eh_frame && first->getAddr() > relhack->getAddr() &&
       second->getAddr() < first_executable->getAddr()) {
     // The distance between both sections needs to be preserved because
     // eh_frame_hdr contains relative offsets to eh_frame. Well, they could be
     // relocated too, but it's not worth the effort for the few number of bytes
     // this would save.
-    unsigned int distance = second->getAddr() - first->getAddr();
-    unsigned int origAddr = eh_frame->getAddr();
+    Elf64_Off distance = second->getAddr() - first->getAddr();
+    Elf64_Addr origAddr = eh_frame->getAddr();
     ElfSection* previous = first->getPrevious();
     first->getShdr().sh_addr = (previous->getAddr() + previous->getSize() +
                                 first->getAddrAlign() - 1) &
                                ~(first->getAddrAlign() - 1);
     second->getShdr().sh_addr =
         (first->getAddr() + std::min(first->getSize(), distance) +
          second->getAddrAlign() - 1) &
         ~(second->getAddrAlign() - 1);
diff --git a/build/unix/elfhack/elfxx.h b/build/unix/elfhack/elfxx.h
--- a/build/unix/elfhack/elfxx.h
+++ b/build/unix/elfhack/elfxx.h
@@ -280,17 +280,17 @@ typedef serializable<Elf_Shdr_Traits> El
 class Elf {
  public:
   Elf(std::ifstream& file);
   ~Elf();
 
   /* index == -1 is treated as index == ehdr.e_shstrndx */
   ElfSection* getSection(int index);
 
-  ElfSection* getSectionAt(unsigned int offset);
+  ElfSection* getSectionAt(Elf64_Off offset);
 
   ElfSegment* getSegmentByType(unsigned int type, ElfSegment* last = nullptr);
 
   ElfDynamic_Section* getDynSection();
 
   void normalize();
   void write(std::ofstream& file);
 
@@ -329,18 +329,18 @@ class ElfSection {
 
   ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent);
 
   virtual ~ElfSection() { free(data); }
 
   const char* getName() { return name; }
   unsigned int getType() { return shdr.sh_type; }
   unsigned int getFlags() { return shdr.sh_flags; }
-  unsigned int getAddr();
-  unsigned int getSize() { return shdr.sh_size; }
+  Elf64_Addr getAddr();
+  Elf64_Off getSize() { return shdr.sh_size; }
   unsigned int getAddrAlign() { return shdr.sh_addralign; }
   unsigned int getEntSize() { return shdr.sh_entsize; }
   const char* getData() { return data; }
   ElfSection* getLink() { return link; }
   SectionInfo getInfo() { return info; }
 
   void shrink(unsigned int newsize) {
     if (newsize < shdr.sh_size) {
@@ -353,17 +353,17 @@ class ElfSection {
     if (newsize > shdr.sh_size) {
       data = static_cast<char*>(realloc(data, newsize));
       memset(data + shdr.sh_size, 0, newsize - shdr.sh_size);
       shdr.sh_size = newsize;
       markDirty();
     }
   }
 
-  unsigned int getOffset();
+  Elf64_Off getOffset();
   int getIndex();
   Elf_Shdr& getShdr();
 
   ElfSection* getNext() { return next; }
   ElfSection* getPrevious() { return previous; }
 
   virtual bool isRelocatable() {
     return ((getType() == SHT_SYMTAB) || (getType() == SHT_STRTAB) ||

