Made the ELF file class configurable.

PiperOrigin-RevId: 712581801
Change-Id: I8ce4cccb01a7536eb0a43e82f7602613a0e04d4f
diff --git a/mpact/sim/util/asm/simple_assembler.cc b/mpact/sim/util/asm/simple_assembler.cc
index f6f1c82..0697ef3 100644
--- a/mpact/sim/util/asm/simple_assembler.cc
+++ b/mpact/sim/util/asm/simple_assembler.cc
@@ -55,10 +55,12 @@
 // resolve symbol names to values.
 class SymbolResolver : public ResolverInterface {
  public:
-  explicit SymbolResolver(
-      ELFIO::section *symtab,
+  SymbolResolver(
+      int elf_file_class, ELFIO::section *symtab,
       const absl::flat_hash_map<std::string, ELFIO::Elf_Xword> &symbol_indices)
-      : symtab_(symtab), symbol_indices_(symbol_indices) {}
+      : elf_file_class_(elf_file_class),
+        symtab_(symtab),
+        symbol_indices_(symbol_indices) {}
   absl::StatusOr<uint64_t> Resolve(absl::string_view text) override {
     auto iter = symbol_indices_.find(text);
     if (iter == symbol_indices_.end()) {
@@ -66,21 +68,32 @@
           absl::StrCat("Symbol '", text, "' not found"));
     }
     auto index = iter->second;
-    auto *sym = reinterpret_cast<const ELFIO::Elf64_Sym *>(symtab_->get_data());
-    return sym[index].st_value;
+    if (elf_file_class_ == ELFCLASS64) {
+      auto *sym =
+          reinterpret_cast<const ELFIO::Elf64_Sym *>(symtab_->get_data());
+      return sym[index].st_value;
+    } else if (elf_file_class_ == ELFCLASS32) {
+      auto *sym =
+          reinterpret_cast<const ELFIO::Elf32_Sym *>(symtab_->get_data());
+      return sym[index].st_value;
+    }
+    return absl::InternalError("Unsupported ELF file class");
   }
 
  private:
+  // Elf file class.
+  int elf_file_class_ = 0;
   // The symbol table ELF section.
   ELFIO::section *symtab_;
   // Map from symbol name to symbol index in the symbol table.
   const absl::flat_hash_map<std::string, ELFIO::Elf_Xword> &symbol_indices_;
 };
 
-SimpleAssembler::SimpleAssembler(int os_abi, int type, int machine,
-                                 uint64_t base_address,
+SimpleAssembler::SimpleAssembler(int elf_file_class, int os_abi, int type,
+                                 int machine, uint64_t base_address,
                                  OpcodeAssemblerInterface *opcode_assembler_if)
-    : opcode_assembler_if_(opcode_assembler_if),
+    : elf_file_class_(elf_file_class),
+      opcode_assembler_if_(opcode_assembler_if),
       base_address_(base_address),
       comment_re_("^\\s*(?:;(.*))?$"),
       asm_line_re_("^(?:(?:(\\S+)\\s*:)?|\\s)\\s*([^;]*?)?\\s*(?:;(.*))?$"),
@@ -91,14 +104,16 @@
           ")?\\s*"
           "$") {
   // Configure the ELF file writer.
-  writer_.create(ELFCLASS64, ELFDATA2LSB);
+  writer_.create(elf_file_class_, ELFDATA2LSB);
   writer_.set_os_abi(os_abi);
   writer_.set_type(ET_EXEC);
   writer_.set_machine(machine);
   // Create the symbol table section.
   symtab_ = writer_.sections.add(".symtab");
   symtab_->set_type(SHT_SYMTAB);
-  symtab_->set_entry_size(sizeof(ELFIO::Elf64_Sym));
+  symtab_->set_entry_size(elf_file_class_ == ELFCLASS64
+                              ? sizeof(ELFIO::Elf64_Sym)
+                              : sizeof(ELFIO::Elf32_Sym));
   // Create the string table section.
   strtab_ = writer_.sections.add(".strtab");
   strtab_->set_type(SHT_STRTAB);
@@ -239,7 +254,8 @@
 
   // For the second pass, we need a symbol resolver that uses the symbol table
   // and the symbol indices.
-  symbol_resolver_ = new SymbolResolver(symtab_, symbol_indices_);
+  symbol_resolver_ =
+      new SymbolResolver(elf_file_class_, symtab_, symbol_indices_);
 
   // Update the section address map so that each section starts at the right
   // address, i.e., it no longer tracks the offset within each section, but the
diff --git a/mpact/sim/util/asm/simple_assembler.h b/mpact/sim/util/asm/simple_assembler.h
index d020583..ce72af9 100644
--- a/mpact/sim/util/asm/simple_assembler.h
+++ b/mpact/sim/util/asm/simple_assembler.h
@@ -51,7 +51,8 @@
 
 class SimpleAssembler {
  public:
-  SimpleAssembler(int os_abi, int type, int machine, uint64_t base_address,
+  SimpleAssembler(int elf_file_class, int os_abi, int type, int machine,
+                  uint64_t base_address,
                   OpcodeAssemblerInterface *opcode_assembler_if);
   SimpleAssembler(const SimpleAssembler &) = delete;
   SimpleAssembler &operator=(const SimpleAssembler &) = delete;
@@ -89,6 +90,8 @@
   void SetDataSection(const std::string &name);
   void SetBssSection(const std::string &name);
 
+  // ELF file class.
+  int elf_file_class_ = 0;
   // Elf file top level object.
   ELFIO::elfio writer_;
   // The current section being processed.
diff --git a/mpact/sim/util/asm/test/riscv64x_asm_test.cc b/mpact/sim/util/asm/test/riscv64x_asm_test.cc
index 3f2e647..00c2558 100644
--- a/mpact/sim/util/asm/test/riscv64x_asm_test.cc
+++ b/mpact/sim/util/asm/test/riscv64x_asm_test.cc
@@ -115,11 +115,12 @@
       : matcher_(&bin_encoder_interface_), riscv_64x_assembler_(&matcher_) {
     CHECK_OK(matcher_.Initialize());
     // Create the assembler.
-    assembler_ = new SimpleAssembler(ELFOSABI_LINUX, ET_EXEC, EM_RISCV, 0x1000,
-                                     &riscv_64x_assembler_);
+    assembler_ = new SimpleAssembler(ELFCLASS64, ELFOSABI_LINUX, ET_EXEC,
+                                     EM_RISCV, 0x1000, &riscv_64x_assembler_);
     std::istringstream source(*kTestAssembly);
     // Parse the assembly code.
-    CHECK_OK(assembler_->Parse(source));
+    auto status = assembler_->Parse(source);
+    CHECK_OK(status) << status.message();
   }
 
   ~RiscV64XAssemblerTest() override { delete assembler_; }