No public description

PiperOrigin-RevId: 949755748
Change-Id: I5dfdff8309d6867ffc734b11de5a2a7adc3333bf
diff --git a/mpact/sim/util/program_loader/elf_program_loader.cc b/mpact/sim/util/program_loader/elf_program_loader.cc
index 6ebb974..a071ab2 100644
--- a/mpact/sim/util/program_loader/elf_program_loader.cc
+++ b/mpact/sim/util/program_loader/elf_program_loader.cc
@@ -26,6 +26,7 @@
 #include "absl/status/statusor.h"
 #include "absl/strings/str_cat.h"
 #include "elfio/elf_types.hpp"
+#include "elfio/elfio_section.hpp"
 #include "elfio/elfio_segment.hpp"
 #include "elfio/elfio_symbols.hpp"
 #include "mpact/sim/generic/core_debug_interface.h"
@@ -42,9 +43,8 @@
                                    util::MemoryInterface* data_memory)
     : code_memory_(code_memory), data_memory_(data_memory) {}
 
-ElfProgramLoader::ElfProgramLoader(
-    const std::vector<MemoryDescriptor>& memories)
-    : memories_(&memories) {}
+ElfProgramLoader::ElfProgramLoader(std::vector<MemoryDescriptor> memories)
+    : memories_(std::move(memories)) {}
 
 ElfProgramLoader::ElfProgramLoader(util::MemoryInterface* memory)
     : code_memory_(memory), data_memory_(memory) {}
@@ -59,6 +59,25 @@
   symbol_accessors_.clear();
 }
 
+int ElfProgramLoader::GetSegmentIndex(int section_index) const {
+  if (section_index < 0 || section_index >= elf_reader_.sections.size()) {
+    return -1;
+  }
+  const ELFIO::section* section = elf_reader_.sections[section_index];
+  auto section_address = section->get_address();
+  for (int i = 0; i < elf_reader_.segments.size(); ++i) {
+    auto const& segment = elf_reader_.segments[i];
+    if (segment->get_type() == ELFIO::PT_LOAD) {
+      if (section_address >= segment->get_virtual_address() &&
+          section_address <
+              segment->get_virtual_address() + segment->get_memory_size()) {
+        return i;
+      }
+    }
+  }
+  return -1;
+}
+
 // Only load the program into the elf reader so that symbols can be looked up.
 absl::StatusOr<uint64_t> ElfProgramLoader::LoadSymbols(
     const std::string& file_name) {
@@ -97,6 +116,21 @@
     for (unsigned i = 0; i < symtab->get_symbols_num(); i++) {
       symtab->get_symbol(i, name, value, size, bind, type, section_index,
                          other);
+      if (!memories_.empty()) {
+        // If there are memory descriptors, we need to figure out how to modify
+        // the symbol address before we store it.
+        int segment_index = GetSegmentIndex(section_index);
+        if (segment_index >= 0) {
+          for (auto& memory : memories_) {
+            if (memory.predicate_fcn(*elf_reader_.segments[segment_index])) {
+              if (memory.address_fcn) {
+                value = memory.address_fcn(value);
+              }
+              break;
+            }
+          }
+        }
+      }
       if (type == ELFIO::STT_FUNC) {
         fcn_symbol_map_.emplace(value, name);
         function_range_map_.insert(
@@ -137,7 +171,7 @@
       auto size = segment->get_file_size();
       auto* db = db_factory.Allocate(size);
       std::memcpy(db->raw_ptr(), segment->get_data(), size);
-      if (memories_ == nullptr) {
+      if (memories_.empty()) {
         if (segment->get_flags() &
             ELFIO::PF_X) {  // Executable, so write to code memory.
           code_memory_->Store(dest_addr, db);
@@ -145,7 +179,7 @@
           data_memory_->Store(dest_addr, db);
         }
       } else {
-        for (auto& memory : *memories_) {
+        for (auto& memory : memories_) {
           if (memory.predicate_fcn(*segment)) {
             if (memory.address_fcn) {
               memory.memory->Store(memory.address_fcn(dest_addr), db);
@@ -185,6 +219,23 @@
   for (auto* symtab : symbol_accessors_) {
     if (symtab->get_symbol(name, value, size, bind, type, section_index,
                            other)) {
+      if (!memories_.empty()) {
+        // If there are memory descriptors, we need to figure out how to modify
+        // the symbol address before we store it.
+        int segment_index = GetSegmentIndex(section_index);
+        if (segment_index >= 0) {
+          for (auto& memory : memories_) {
+            auto const& segment = elf_reader_.segments[segment_index];
+            if (memory.predicate_fcn && memory.predicate_fcn(*segment)) {
+              if (memory.address_fcn) {
+                value = memory.address_fcn(value);
+                size = memory.address_fcn(size);
+              }
+              break;
+            }
+          }
+        }
+      }
       return std::make_pair(static_cast<uint64_t>(value),
                             static_cast<uint64_t>(size));
     }
diff --git a/mpact/sim/util/program_loader/elf_program_loader.h b/mpact/sim/util/program_loader/elf_program_loader.h
index a1ae625..93333c2 100644
--- a/mpact/sim/util/program_loader/elf_program_loader.h
+++ b/mpact/sim/util/program_loader/elf_program_loader.h
@@ -79,7 +79,7 @@
  public:
   ElfProgramLoader(util::MemoryInterface* code_memory,
                    util::MemoryInterface* data_memory);
-  ElfProgramLoader(const std::vector<MemoryDescriptor>& memories);
+  ElfProgramLoader(std::vector<MemoryDescriptor> memories);
   explicit ElfProgramLoader(util::MemoryInterface* memory);
   explicit ElfProgramLoader(generic::CoreDebugInterface* dbg_if);
   ElfProgramLoader() = delete;
@@ -105,7 +105,8 @@
   const ELFIO::elfio* elf_reader() const { return &elf_reader_; }
 
  private:
-  const std::vector<MemoryDescriptor>* memories_ = nullptr;
+  int GetSegmentIndex(int section_index) const;
+  const std::vector<MemoryDescriptor> memories_;
   bool loaded_ = false;
   ELFIO::elfio elf_reader_;
   util::MemoryInterface* code_memory_ = nullptr;