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

Commit 1baa19b1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Fix offsets when shared lib split across maps."

parents 61367404 a09c4a6f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
    back_frame->map.name = frame->map_name;
    back_frame->map.start = frame->map_start;
    back_frame->map.end = frame->map_end;
    back_frame->map.offset = frame->map_offset;
    back_frame->map.offset = frame->map_elf_start_offset;
    back_frame->map.load_bias = frame->map_load_bias;
    back_frame->map.flags = frame->map_flags;
  }
+37 −48
Original line number Diff line number Diff line
@@ -32,34 +32,28 @@ namespace unwindstack {
bool MapInfo::InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory) {
  // One last attempt, see if the previous map is read-only with the
  // same name and stretches across this map.
  for (auto iter = maps_->begin(); iter != maps_->end(); ++iter) {
    if (*iter == this) {
      if (iter == maps_->begin()) {
        return false;
      }
      --iter;
      MapInfo* prev_map = *iter;
      // Make sure this is a read-only map.
      if (prev_map->flags != PROT_READ) {
  if (prev_map == nullptr || prev_map->flags != PROT_READ) {
    return false;
  }

  uint64_t map_size = end - prev_map->end;
  if (!memory->Init(name, prev_map->offset, map_size)) {
    return false;
  }

  uint64_t max_size;
  if (!Elf::GetInfo(memory, &max_size) || max_size < map_size) {
    return false;
  }

  if (!memory->Init(name, prev_map->offset, max_size)) {
    return false;
  }

  elf_offset = offset - prev_map->offset;
  elf_start_offset = prev_map->offset;
  return true;
}
  }
  return false;
}

Memory* MapInfo::GetFileMemory() {
  std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset);
@@ -91,14 +85,13 @@ Memory* MapInfo::GetFileMemory() {

  // Check if the start of this map is an embedded elf.
  uint64_t max_size = 0;
  uint64_t file_offset = offset;
  if (Elf::GetInfo(memory.get(), &max_size)) {
    if (max_size > map_size) {
      if (memory->Init(name, file_offset, max_size)) {
      if (memory->Init(name, offset, max_size)) {
        return memory.release();
      }
      // Try to reinit using the default map_size.
      if (memory->Init(name, file_offset, map_size)) {
      if (memory->Init(name, offset, map_size)) {
        return memory.release();
      }
      return nullptr;
@@ -109,6 +102,13 @@ Memory* MapInfo::GetFileMemory() {
  // No elf at offset, try to init as if the whole file is an elf.
  if (memory->Init(name, 0) && Elf::IsValidElf(memory.get())) {
    elf_offset = offset;
    // Need to check how to set the elf start offset. If this map is not
    // the r-x map of a r-- map, then use the real offset value. Otherwise,
    // use 0.
    if (prev_map == nullptr || prev_map->offset != 0 || prev_map->flags != PROT_READ ||
        prev_map->name != name) {
      elf_start_offset = offset;
    }
    return memory.release();
  }

@@ -156,35 +156,24 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
    return memory.release();
  }

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

  // Find the read-only map by looking at the previous map. The linker
  // doesn't guarantee that this invariant will always be true. However,
  // if that changes, there is likely something else that will change and
  // break something.
  MapInfo* ro_map_info = nullptr;
  for (auto iter = maps_->begin(); iter != maps_->end(); ++iter) {
    if (*iter == this) {
      if (iter != maps_->begin()) {
        --iter;
        ro_map_info = *iter;
      }
      break;
    }
  }

  if (ro_map_info == nullptr || ro_map_info->name != name || ro_map_info->offset >= offset) {
  if (offset == 0 || name.empty() || prev_map == nullptr || prev_map->name != name ||
      prev_map->offset >= offset) {
    return nullptr;
  }

  // Make sure that relative pc values are corrected properly.
  elf_offset = offset - ro_map_info->offset;
  elf_offset = offset - prev_map->offset;
  // Use this as the elf start offset, otherwise, you always get offsets into
  // the r-x section, which is not quite the right information.
  elf_start_offset = prev_map->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, prev_map->start, prev_map->end - prev_map->start, 0));
  ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset));

  return ranges;
+13 −3
Original line number Diff line number Diff line
@@ -67,13 +67,15 @@ 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(this, start, end, pgoff, flags, name));
        maps_.push_back(
            new MapInfo(maps_.empty() ? nullptr : maps_.back(), 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(this, start, end, offset, flags, name);
  MapInfo* map_info =
      new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, offset, flags, name);
  map_info->load_bias = load_bias;
  maps_.push_back(map_info);
}
@@ -81,6 +83,13 @@ void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
void Maps::Sort() {
  std::sort(maps_.begin(), maps_.end(),
            [](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });

  // Set the prev_map values on the info objects.
  MapInfo* prev_map = nullptr;
  for (MapInfo* map_info : maps_) {
    map_info->prev_map = prev_map;
    prev_map = map_info;
  }
}

Maps::~Maps() {
@@ -98,7 +107,8 @@ 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(this, start, end, pgoff, flags, name));
        maps_.push_back(
            new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
      });
}

+9 −6
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ void Unwinder::FillInDexFrame() {
  if (info != nullptr) {
    frame->map_start = info->start;
    frame->map_end = info->end;
    frame->map_offset = info->offset;
    frame->map_elf_start_offset = info->elf_start_offset;
    frame->map_exact_offset = info->offset;
    frame->map_load_bias = info->load_bias;
    frame->map_flags = info->flags;
    if (resolve_names_) {
@@ -102,7 +103,8 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_
  if (resolve_names_) {
    frame->map_name = map_info->name;
  }
  frame->map_offset = map_info->offset;
  frame->map_elf_start_offset = map_info->elf_start_offset;
  frame->map_exact_offset = map_info->offset;
  frame->map_start = map_info->start;
  frame->map_end = map_info->end;
  frame->map_flags = map_info->flags;
@@ -290,10 +292,6 @@ std::string Unwinder::FormatFrame(const FrameData& frame, bool is32bit) {
    data += android::base::StringPrintf("  #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
  }

  if (frame.map_offset != 0) {
    data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_offset);
  }

  if (frame.map_start == frame.map_end) {
    // No valid map associated with this frame.
    data += "  <unknown>";
@@ -302,6 +300,11 @@ std::string Unwinder::FormatFrame(const FrameData& frame, bool is32bit) {
  } else {
    data += android::base::StringPrintf("  <anonymous:%" PRIx64 ">", frame.map_start);
  }

  if (frame.map_elf_start_offset != 0) {
    data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_elf_start_offset);
  }

  if (!frame.function_name.empty()) {
    data += " (" + frame.function_name;
    if (frame.function_offset != 0) {
+14 −17
Original line number Diff line number Diff line
@@ -25,38 +25,31 @@
#include <string>

#include <unwindstack/Elf.h>
#include <unwindstack/Memory.h>

namespace unwindstack {

// Forward declarations.
class Maps;
class Memory;

struct MapInfo {
  MapInfo(Maps* maps) : maps_(maps) {}
  MapInfo(Maps* maps, uint64_t start, uint64_t end) : maps_(maps), start(start), end(end) {}
  MapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
  MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
          const char* name)
      : maps_(maps),
        start(start),
      : start(start),
        end(end),
        offset(offset),
        flags(flags),
        name(name),
        prev_map(map_info),
        load_bias(static_cast<uint64_t>(-1)) {}
  MapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
  MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
          const std::string& name)
      : maps_(maps),
        start(start),
      : start(start),
        end(end),
        offset(offset),
        flags(flags),
        name(name),
        prev_map(map_info),
        load_bias(static_cast<uint64_t>(-1)) {}
  ~MapInfo() = default;

  Maps* maps_ = nullptr;

  uint64_t start = 0;
  uint64_t end = 0;
  uint64_t offset = 0;
@@ -64,10 +57,14 @@ struct MapInfo {
  std::string name;
  std::shared_ptr<Elf> elf;
  // This value is only non-zero if the offset is non-zero but there is
  // no elf signature found at that offset. This indicates that the
  // entire file is represented by the Memory object returned by CreateMemory,
  // instead of a portion of the file.
  // no elf signature found at that offset.
  uint64_t elf_offset = 0;
  // This value is the offset from the map in memory that is the start
  // of the elf. This is not equal to offset when the linker splits
  // shared libraries into a read-only and read-execute map.
  uint64_t elf_start_offset = 0;

  MapInfo* prev_map = nullptr;

  std::atomic_uint64_t load_bias;

Loading