diff options
author | Cheng Hann Gan <chenghanngan.us@gmail.com> | 2021-09-09 19:22:48 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 16:22:48 -0700 |
commit | 8237e29a164211eb2ec4cd161eb4183cc1947fee (patch) | |
tree | 67dc502264b755dc620f56969f3bea68a40b17af /tools/ramscrgen/elf.cpp | |
parent | 4eff1882443b0004d9c9fa4895cdfefdc356565f (diff) |
Defined more in-dungeon structs and enums (#53)
* Defined DungeonEntity
* Rename EntityType enums
* Revert EntityType rename
* Defined more in-dungeon structs and enums
* Added more dungeon global structs/enums
* Prefixed dungeonGlobalData with g
* Fixed compile errors
* Removed some CRLFs
* Fixed compile after merge
* Revert Makefile
* Rename DungeonEntityData.entityType
Co-authored-by: Seth Barberee <seth.barberee@gmail.com>
* Renamed symbols per PR comments
Co-authored-by: Cheng Hann Gan <chenghann_gan@ultimatesoftware.com>
Co-authored-by: Seth Barberee <seth.barberee@gmail.com>
Diffstat (limited to 'tools/ramscrgen/elf.cpp')
-rw-r--r-- | tools/ramscrgen/elf.cpp | 544 |
1 files changed, 272 insertions, 272 deletions
diff --git a/tools/ramscrgen/elf.cpp b/tools/ramscrgen/elf.cpp index 7cef9f9..7e78704 100644 --- a/tools/ramscrgen/elf.cpp +++ b/tools/ramscrgen/elf.cpp @@ -1,272 +1,272 @@ -#include <cstdio>
-#include <cstring>
-#include <cstdint>
-#include <map>
-#include <vector>
-#include <string>
-#include "ramscrgen.h"
-#include "elf.h"
-
-#define SHN_COMMON 0xFFF2
-
-static std::string s_elfPath;
-static std::string s_archiveFilePath;
-static std::string s_archiveObjectPath;
-
-static FILE *s_file;
-
-static std::uint32_t s_sectionHeaderOffset;
-static int s_sectionHeaderEntrySize;
-static int s_sectionCount;
-static int s_shstrtabIndex;
-
-static std::uint32_t s_symtabOffset;
-static std::uint32_t s_strtabOffset;
-
-static std::uint32_t s_symbolCount;
-static std::uint32_t s_elfFileOffset;
-
-struct Symbol
-{
- std::uint32_t nameOffset;
- std::uint32_t size;
-};
-
-static void Seek(long offset)
-{
- if (std::fseek(s_file, s_elfFileOffset + offset, SEEK_SET) != 0)
- FATAL_ERROR("error: failed to seek to %ld in \"%s\"", offset, s_elfPath.c_str());
-}
-
-static void Skip(long offset)
-{
- if (std::fseek(s_file, offset, SEEK_CUR) != 0)
- FATAL_ERROR("error: failed to skip %ld bytes in \"%s\"", offset, s_elfPath.c_str());
-}
-
-static std::uint32_t ReadInt8()
-{
- int c = std::fgetc(s_file);
-
- if (c < 0)
- FATAL_ERROR("error: unexpected EOF when reading ELF file \"%s\"\n", s_elfPath.c_str());
-
- return c;
-}
-
-static std::uint32_t ReadInt16()
-{
- std::uint32_t val = 0;
- val |= ReadInt8();
- val |= ReadInt8() << 8;
- return val;
-}
-
-static std::uint32_t ReadInt32()
-{
- std::uint32_t val = 0;
- val |= ReadInt8();
- val |= ReadInt8() << 8;
- val |= ReadInt8() << 16;
- val |= ReadInt8() << 24;
- return val;
-}
-
-static std::string ReadString()
-{
- std::string s;
- char c;
-
- while ((c = ReadInt8()) != 0)
- s += c;
-
- return s;
-}
-
-static void VerifyElfIdent()
-{
- char expectedMagic[4] = { 0x7F, 'E', 'L', 'F' };
- char magic[4];
-
- if (std::fread(magic, 4, 1, s_file) != 1)
- FATAL_ERROR("error: failed to read ELF magic from \"%s\"\n", s_elfPath.c_str());
-
- if (std::memcmp(magic, expectedMagic, 4) != 0)
- FATAL_ERROR("error: ELF magic did not match in \"%s\"\n", s_elfPath.c_str());
-
- if (std::fgetc(s_file) != 1)
- FATAL_ERROR("error: \"%s\" not 32-bit ELF\n", s_elfPath.c_str());
-
- if (std::fgetc(s_file) != 1)
- FATAL_ERROR("error: \"%s\" not little-endian ELF\n", s_elfPath.c_str());
-}
-
-static void VerifyAr()
-{
- char expectedMagic[8] = {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'};
- char magic[8];
-
- if (std::fread(magic, 8, 1, s_file) != 1)
- FATAL_ERROR("error: failed to read AR magic from \"%s\"\n", s_archiveFilePath.c_str());
-
- if (std::memcmp(magic, expectedMagic, 8) != 0)
- FATAL_ERROR("error: AR magic did not match in \"%s\"\n", s_archiveFilePath.c_str());
-}
-
-static void ReadElfHeader()
-{
- Seek(0x20);
- s_sectionHeaderOffset = ReadInt32();
- Seek(0x2E);
- s_sectionHeaderEntrySize = ReadInt16();
- s_sectionCount = ReadInt16();
- s_shstrtabIndex = ReadInt16();
-}
-
-static void FindArObj()
-{
- char file_ident[17] = {0};
- char filesize_s[11] = {0};
- char expectedEndMagic[2] = { 0x60, 0x0a };
- char end_magic[2];
- std::size_t filesize;
-
- Seek(8);
- while (!std::feof(s_file)) {
- if (std::fread(file_ident, 16, 1, s_file) != 1)
- FATAL_ERROR("error: failed to read file ident in \"%s\"\n", s_archiveFilePath.c_str());
- Skip(32);
- if (std::fread(filesize_s, 10, 1, s_file) != 1)
- FATAL_ERROR("error: failed to read filesize in \"%s\"\n", s_archiveFilePath.c_str());
- if (std::fread(end_magic, 2, 1, s_file) != 1)
- FATAL_ERROR("error: failed to read end sentinel in \"%s\"\n", s_archiveFilePath.c_str());
- if (std::memcmp(end_magic, expectedEndMagic, 2) != 0)
- FATAL_ERROR("error: corrupted archive header in \"%s\" at \"%s\"\n", s_archiveFilePath.c_str(), file_ident);
-
- char * ptr = std::strchr(file_ident, '/');
- if (ptr != nullptr)
- *ptr = 0;
- filesize = std::strtoul(filesize_s, nullptr, 10);
- if (std::strncmp(s_archiveObjectPath.c_str(), file_ident, 16) == 0) {
- s_elfFileOffset = std::ftell(s_file);
- return;
- }
- Skip(filesize);
- }
-
- FATAL_ERROR("error: could not find object \"%s\" in archive \"%s\"\n", s_archiveObjectPath.c_str(), s_archiveFilePath.c_str());
-}
-
-static std::string GetSectionName(std::uint32_t shstrtabOffset, int index)
-{
- Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * index);
- std::uint32_t nameOffset = ReadInt32();
- Seek(shstrtabOffset + nameOffset);
- return ReadString();
-}
-
-static void FindTableOffsets()
-{
- s_symtabOffset = 0;
- s_strtabOffset = 0;
-
- Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * s_shstrtabIndex + 0x10);
- std::uint32_t shstrtabOffset = ReadInt32();
-
- for (int i = 0; i < s_sectionCount; i++)
- {
- std::string name = GetSectionName(shstrtabOffset, i);
-
- if (name == ".symtab")
- {
- if (s_symtabOffset)
- FATAL_ERROR("error: mutiple .symtab sections found in \"%s\"\n", s_elfPath.c_str());
- Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10);
- s_symtabOffset = ReadInt32();
- std::uint32_t size = ReadInt32();
- s_symbolCount = size / 16;
- }
- else if (name == ".strtab")
- {
- if (s_strtabOffset)
- FATAL_ERROR("error: mutiple .strtab sections found in \"%s\"\n", s_elfPath.c_str());
- Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10);
- s_strtabOffset = ReadInt32();
- }
- }
-
- if (!s_symtabOffset)
- FATAL_ERROR("error: couldn't find .symtab section in \"%s\"\n", s_elfPath.c_str());
-
- if (!s_strtabOffset)
- FATAL_ERROR("error: couldn't find .strtab section in \"%s\"\n", s_elfPath.c_str());
-}
-
-static std::map<std::string, std::uint32_t> GetCommonSymbols_Shared()
-{
- VerifyElfIdent();
- ReadElfHeader();
- FindTableOffsets();
-
- std::map<std::string, std::uint32_t> commonSymbols;
-
- std::vector<Symbol> commonSymbolVec;
-
- Seek(s_symtabOffset);
-
- for (std::uint32_t i = 0; i < s_symbolCount; i++)
- {
- Symbol sym;
- sym.nameOffset = ReadInt32();
- Skip(4);
- sym.size = ReadInt32();
- Skip(2);
- std::uint16_t sectionIndex = ReadInt16();
- if (sectionIndex == SHN_COMMON)
- commonSymbolVec.push_back(sym);
- }
-
- for (const Symbol& sym : commonSymbolVec)
- {
- Seek(s_strtabOffset + sym.nameOffset);
- std::string name = ReadString();
- commonSymbols[name] = sym.size;
- }
-
- return commonSymbols;
-}
-
-std::map<std::string, std::uint32_t> GetCommonSymbolsFromLib(std::string sourcePath, std::string libpath)
-{
- std::size_t colonPos = libpath.find(':');
- if (colonPos == std::string::npos)
- FATAL_ERROR("error: missing colon separator in libfile \"%s\"\n", s_elfPath.c_str());
-
- s_archiveObjectPath = libpath.substr(colonPos + 1);
- s_archiveFilePath = sourcePath + "/" + libpath.substr(1, colonPos - 1);
- s_elfPath = sourcePath + "/" + libpath.substr(1);
-
- s_file = std::fopen(s_archiveFilePath.c_str(), "rb");
-
- if (s_file == NULL)
- FATAL_ERROR("error: failed to open \"%s\" for reading\n", s_archiveFilePath.c_str());
-
- VerifyAr();
- FindArObj();
- return GetCommonSymbols_Shared();
-}
-
-std::map<std::string, std::uint32_t> GetCommonSymbols(std::string sourcePath, std::string path)
-{
- s_elfFileOffset = 0;
- if (path[0] == '*')
- return GetCommonSymbolsFromLib(sourcePath, path);
-
- s_elfPath = sourcePath + "/" + path;
- s_file = std::fopen(s_elfPath.c_str(), "rb");
-
- if (s_file == NULL)
- FATAL_ERROR("error: failed to open \"%s\" for reading\n", path.c_str());
-
- return GetCommonSymbols_Shared();
-}
+#include <cstdio> +#include <cstring> +#include <cstdint> +#include <map> +#include <vector> +#include <string> +#include "ramscrgen.h" +#include "elf.h" + +#define SHN_COMMON 0xFFF2 + +static std::string s_elfPath; +static std::string s_archiveFilePath; +static std::string s_archiveObjectPath; + +static FILE *s_file; + +static std::uint32_t s_sectionHeaderOffset; +static int s_sectionHeaderEntrySize; +static int s_sectionCount; +static int s_shstrtabIndex; + +static std::uint32_t s_symtabOffset; +static std::uint32_t s_strtabOffset; + +static std::uint32_t s_symbolCount; +static std::uint32_t s_elfFileOffset; + +struct Symbol +{ + std::uint32_t nameOffset; + std::uint32_t size; +}; + +static void Seek(long offset) +{ + if (std::fseek(s_file, s_elfFileOffset + offset, SEEK_SET) != 0) + FATAL_ERROR("error: failed to seek to %ld in \"%s\"", offset, s_elfPath.c_str()); +} + +static void Skip(long offset) +{ + if (std::fseek(s_file, offset, SEEK_CUR) != 0) + FATAL_ERROR("error: failed to skip %ld bytes in \"%s\"", offset, s_elfPath.c_str()); +} + +static std::uint32_t ReadInt8() +{ + int c = std::fgetc(s_file); + + if (c < 0) + FATAL_ERROR("error: unexpected EOF when reading ELF file \"%s\"\n", s_elfPath.c_str()); + + return c; +} + +static std::uint32_t ReadInt16() +{ + std::uint32_t val = 0; + val |= ReadInt8(); + val |= ReadInt8() << 8; + return val; +} + +static std::uint32_t ReadInt32() +{ + std::uint32_t val = 0; + val |= ReadInt8(); + val |= ReadInt8() << 8; + val |= ReadInt8() << 16; + val |= ReadInt8() << 24; + return val; +} + +static std::string ReadString() +{ + std::string s; + char c; + + while ((c = ReadInt8()) != 0) + s += c; + + return s; +} + +static void VerifyElfIdent() +{ + char expectedMagic[4] = { 0x7F, 'E', 'L', 'F' }; + char magic[4]; + + if (std::fread(magic, 4, 1, s_file) != 1) + FATAL_ERROR("error: failed to read ELF magic from \"%s\"\n", s_elfPath.c_str()); + + if (std::memcmp(magic, expectedMagic, 4) != 0) + FATAL_ERROR("error: ELF magic did not match in \"%s\"\n", s_elfPath.c_str()); + + if (std::fgetc(s_file) != 1) + FATAL_ERROR("error: \"%s\" not 32-bit ELF\n", s_elfPath.c_str()); + + if (std::fgetc(s_file) != 1) + FATAL_ERROR("error: \"%s\" not little-endian ELF\n", s_elfPath.c_str()); +} + +static void VerifyAr() +{ + char expectedMagic[8] = {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}; + char magic[8]; + + if (std::fread(magic, 8, 1, s_file) != 1) + FATAL_ERROR("error: failed to read AR magic from \"%s\"\n", s_archiveFilePath.c_str()); + + if (std::memcmp(magic, expectedMagic, 8) != 0) + FATAL_ERROR("error: AR magic did not match in \"%s\"\n", s_archiveFilePath.c_str()); +} + +static void ReadElfHeader() +{ + Seek(0x20); + s_sectionHeaderOffset = ReadInt32(); + Seek(0x2E); + s_sectionHeaderEntrySize = ReadInt16(); + s_sectionCount = ReadInt16(); + s_shstrtabIndex = ReadInt16(); +} + +static void FindArObj() +{ + char file_ident[17] = {0}; + char filesize_s[11] = {0}; + char expectedEndMagic[2] = { 0x60, 0x0a }; + char end_magic[2]; + std::size_t filesize; + + Seek(8); + while (!std::feof(s_file)) { + if (std::fread(file_ident, 16, 1, s_file) != 1) + FATAL_ERROR("error: failed to read file ident in \"%s\"\n", s_archiveFilePath.c_str()); + Skip(32); + if (std::fread(filesize_s, 10, 1, s_file) != 1) + FATAL_ERROR("error: failed to read filesize in \"%s\"\n", s_archiveFilePath.c_str()); + if (std::fread(end_magic, 2, 1, s_file) != 1) + FATAL_ERROR("error: failed to read end sentinel in \"%s\"\n", s_archiveFilePath.c_str()); + if (std::memcmp(end_magic, expectedEndMagic, 2) != 0) + FATAL_ERROR("error: corrupted archive header in \"%s\" at \"%s\"\n", s_archiveFilePath.c_str(), file_ident); + + char * ptr = std::strchr(file_ident, '/'); + if (ptr != nullptr) + *ptr = 0; + filesize = std::strtoul(filesize_s, nullptr, 10); + if (std::strncmp(s_archiveObjectPath.c_str(), file_ident, 16) == 0) { + s_elfFileOffset = std::ftell(s_file); + return; + } + Skip(filesize); + } + + FATAL_ERROR("error: could not find object \"%s\" in archive \"%s\"\n", s_archiveObjectPath.c_str(), s_archiveFilePath.c_str()); +} + +static std::string GetSectionName(std::uint32_t shstrtabOffset, int index) +{ + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * index); + std::uint32_t nameOffset = ReadInt32(); + Seek(shstrtabOffset + nameOffset); + return ReadString(); +} + +static void FindTableOffsets() +{ + s_symtabOffset = 0; + s_strtabOffset = 0; + + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * s_shstrtabIndex + 0x10); + std::uint32_t shstrtabOffset = ReadInt32(); + + for (int i = 0; i < s_sectionCount; i++) + { + std::string name = GetSectionName(shstrtabOffset, i); + + if (name == ".symtab") + { + if (s_symtabOffset) + FATAL_ERROR("error: mutiple .symtab sections found in \"%s\"\n", s_elfPath.c_str()); + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10); + s_symtabOffset = ReadInt32(); + std::uint32_t size = ReadInt32(); + s_symbolCount = size / 16; + } + else if (name == ".strtab") + { + if (s_strtabOffset) + FATAL_ERROR("error: mutiple .strtab sections found in \"%s\"\n", s_elfPath.c_str()); + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10); + s_strtabOffset = ReadInt32(); + } + } + + if (!s_symtabOffset) + FATAL_ERROR("error: couldn't find .symtab section in \"%s\"\n", s_elfPath.c_str()); + + if (!s_strtabOffset) + FATAL_ERROR("error: couldn't find .strtab section in \"%s\"\n", s_elfPath.c_str()); +} + +static std::map<std::string, std::uint32_t> GetCommonSymbols_Shared() +{ + VerifyElfIdent(); + ReadElfHeader(); + FindTableOffsets(); + + std::map<std::string, std::uint32_t> commonSymbols; + + std::vector<Symbol> commonSymbolVec; + + Seek(s_symtabOffset); + + for (std::uint32_t i = 0; i < s_symbolCount; i++) + { + Symbol sym; + sym.nameOffset = ReadInt32(); + Skip(4); + sym.size = ReadInt32(); + Skip(2); + std::uint16_t sectionIndex = ReadInt16(); + if (sectionIndex == SHN_COMMON) + commonSymbolVec.push_back(sym); + } + + for (const Symbol& sym : commonSymbolVec) + { + Seek(s_strtabOffset + sym.nameOffset); + std::string name = ReadString(); + commonSymbols[name] = sym.size; + } + + return commonSymbols; +} + +std::map<std::string, std::uint32_t> GetCommonSymbolsFromLib(std::string sourcePath, std::string libpath) +{ + std::size_t colonPos = libpath.find(':'); + if (colonPos == std::string::npos) + FATAL_ERROR("error: missing colon separator in libfile \"%s\"\n", s_elfPath.c_str()); + + s_archiveObjectPath = libpath.substr(colonPos + 1); + s_archiveFilePath = sourcePath + "/" + libpath.substr(1, colonPos - 1); + s_elfPath = sourcePath + "/" + libpath.substr(1); + + s_file = std::fopen(s_archiveFilePath.c_str(), "rb"); + + if (s_file == NULL) + FATAL_ERROR("error: failed to open \"%s\" for reading\n", s_archiveFilePath.c_str()); + + VerifyAr(); + FindArObj(); + return GetCommonSymbols_Shared(); +} + +std::map<std::string, std::uint32_t> GetCommonSymbols(std::string sourcePath, std::string path) +{ + s_elfFileOffset = 0; + if (path[0] == '*') + return GetCommonSymbolsFromLib(sourcePath, path); + + s_elfPath = sourcePath + "/" + path; + s_file = std::fopen(s_elfPath.c_str(), "rb"); + + if (s_file == NULL) + FATAL_ERROR("error: failed to open \"%s\" for reading\n", path.c_str()); + + return GetCommonSymbols_Shared(); +} |