Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3a7ddcf authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Implement support for linker rosegment option."

parents 29553d2d 9d5712c1
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -116,10 +116,6 @@ cc_test_library {

    target: {
        linux_glibc: {
            // The host uses rosegment, which isn't supported yet.
            ldflags: [
                "-Wl,--no-rosegment",
            ],
            // This forces the creation of eh_frame with unwind information
            // for host.
            cflags: [
+2 −0
Original line number Diff line number Diff line
@@ -178,6 +178,7 @@ cc_test {
        "tests/JitDebugTest.cpp",
        "tests/LocalUnwinderTest.cpp",
        "tests/LogFake.cpp",
        "tests/MapInfoCreateMemoryTest.cpp",
        "tests/MapInfoGetElfTest.cpp",
        "tests/MapInfoGetLoadBiasTest.cpp",
        "tests/MapsTest.cpp",
@@ -188,6 +189,7 @@ cc_test {
        "tests/MemoryOfflineBufferTest.cpp",
        "tests/MemoryOfflineTest.cpp",
        "tests/MemoryRangeTest.cpp",
        "tests/MemoryRangesTest.cpp",
        "tests/MemoryRemoteTest.cpp",
        "tests/MemoryTest.cpp",
        "tests/RegsInfoTest.cpp",
+48 −1
Original line number Diff line number Diff line
@@ -102,7 +102,54 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
  if (!(flags & PROT_READ)) {
    return nullptr;
  }
  return new MemoryRange(process_memory, start, end - start, 0);

  // Need to verify that this elf is valid. It's possible that
  // only part of the elf file to be mapped into memory is in the executable
  // map. In this case, there will be another read-only map that includes the
  // first part of the elf file. This is done if the linker rosegment
  // option is used.
  std::unique_ptr<MemoryRange> memory(new MemoryRange(process_memory, start, end - start, 0));
  bool valid;
  uint64_t max_size;
  Elf::GetInfo(memory.get(), &valid, &max_size);
  if (valid) {
    // Valid elf, we are done.
    return memory.release();
  }

  if (name.empty() || maps_ == nullptr) {
    return nullptr;
  }

  // Find the read-only map that has the same name and has an offset closest
  // to the current offset but less than the offset of the current map.
  // For shared libraries, there should be a r-x map that has a non-zero
  // offset and then a r-- map that has a zero offset.
  // For shared libraries loaded from an apk, there should be a r-x map that
  // has a non-zero offset and then a r-- map that has a non-zero offset less
  // than the offset from the r-x map.
  uint64_t closest_offset = 0;
  MapInfo* ro_map_info = nullptr;
  for (auto map_info : *maps_) {
    if (map_info->flags == PROT_READ && map_info->name == name && map_info->offset < offset &&
        map_info->offset >= closest_offset) {
      ro_map_info = map_info;
      closest_offset = ro_map_info->offset;
    }
  }

  if (ro_map_info != nullptr) {
    // Make sure that relative pc values are corrected properly.
    elf_offset = offset - closest_offset;

    MemoryRanges* ranges = new MemoryRanges;
    ranges->Insert(new MemoryRange(process_memory, ro_map_info->start,
                                   ro_map_info->end - ro_map_info->start, 0));
    ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset));

    return ranges;
  }
  return nullptr;
}

Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
+3 −3
Original line number Diff line number Diff line
@@ -66,13 +66,13 @@ bool Maps::Parse() {
        if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
          flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
        }
        maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
        maps_.push_back(new MapInfo(this, start, end, pgoff, flags, name));
      });
}

void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
               const std::string& name, uint64_t load_bias) {
  MapInfo* map_info = new MapInfo(start, end, offset, flags, name);
  MapInfo* map_info = new MapInfo(this, start, end, offset, flags, name);
  map_info->load_bias = load_bias;
  maps_.push_back(map_info);
}
@@ -97,7 +97,7 @@ bool BufferMaps::Parse() {
        if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
          flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
        }
        maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
        maps_.push_back(new MapInfo(this, start, end, pgoff, flags, name));
      });
}

+12 −0
Original line number Diff line number Diff line
@@ -316,6 +316,18 @@ size_t MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
  return memory_->Read(read_addr, dst, read_length);
}

void MemoryRanges::Insert(MemoryRange* memory) {
  maps_.emplace(memory->offset() + memory->length(), memory);
}

size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) {
  auto entry = maps_.upper_bound(addr);
  if (entry != maps_.end()) {
    return entry->second->Read(addr, dst, size);
  }
  return 0;
}

bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
  auto memory_file = std::make_shared<MemoryFileAtOffset>();
  if (!memory_file->Init(file, offset)) {
Loading