mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
[nstool|fnd|hac] Fixed bugs in elf symbol processing (NSO|NRO handling).
This commit is contained in:
parent
7b2d682203
commit
9bef414510
|
@ -1,216 +1,458 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
typedef byte_t Elf_Byte;
|
namespace fnd
|
||||||
typedef word_t Elf32_Addr;
|
|
||||||
typedef word_t Elf32_Off;
|
|
||||||
typedef long_t Elf32_Sword; // lol "sword"
|
|
||||||
typedef word_t Elf32_Word;
|
|
||||||
typedef hword_t Elf32_Half;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
{
|
||||||
EI_MAG0 = 0, // 0x7F
|
namespace elf
|
||||||
EI_MAG1 = 1, // 'E'
|
{
|
||||||
EI_MAG2 = 2, // 'L'
|
/* These constants are for the segment types stored in the image headers */
|
||||||
EI_MAG3 = 3, // 'F'
|
enum SegmentType
|
||||||
EI_CLASS = 4, // File class
|
{
|
||||||
EI_DATA = 5, // Data encoding
|
PT_NULL = 0,
|
||||||
EI_VERSION = 6, // File version
|
PT_LOAD = 1,
|
||||||
EI_PAD = 7, // Start of padding bytes
|
PT_DYNAMIC = 2,
|
||||||
EI_NIDENT = 16 // Size of e_ident[]
|
PT_INTERP = 3,
|
||||||
};
|
PT_NOTE = 4,
|
||||||
|
PT_SHLIB = 5,
|
||||||
|
PT_PHDR = 6,
|
||||||
|
PT_TLS = 7, /* Thread local storage segment */
|
||||||
|
PT_LOOS = 0x60000000, /* OS-specific */
|
||||||
|
PT_HIOS = 0x6fffffff, /* OS-specific */
|
||||||
|
PT_LOPROC = 0x70000000,
|
||||||
|
PT_HIPROC = 0x7fffffff
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
/* These constants define the different elf file types */
|
||||||
{
|
enum ElfType
|
||||||
unsigned char e_ident[EI_NIDENT]; // Identification bytes
|
{
|
||||||
Elf32_Half e_type; // Object file type
|
ET_NONE = 0,
|
||||||
Elf32_Half e_machine; // Object architecture
|
ET_REL = 1,
|
||||||
Elf32_Word e_version; // Object file version
|
ET_EXEC = 2,
|
||||||
Elf32_Addr e_entry; // Object entry point
|
ET_DYN = 3,
|
||||||
Elf32_Off e_phoff; // Program header file offset
|
ET_CORE = 4,
|
||||||
Elf32_Off e_shoff; // Section header file offset
|
ET_LOPROC = 0xff00,
|
||||||
Elf32_Word e_flags; // Processor-specific flags
|
ET_HIPROC = 0xffff
|
||||||
Elf32_Half e_ehsize; // ELF header size
|
};
|
||||||
Elf32_Half e_phentsize; // Program header entry size
|
|
||||||
Elf32_Half e_phnum; // Program header entries
|
|
||||||
Elf32_Half e_shentsize; // Section header entry size
|
|
||||||
Elf32_Half e_shnum; // Section header entries
|
|
||||||
Elf32_Half e_shstrndx; // String table index
|
|
||||||
} Elf32_Ehdr;
|
|
||||||
|
|
||||||
typedef struct
|
/* This is the info that is needed to parse the dynamic section of the file */
|
||||||
{
|
enum DynamicSectionType
|
||||||
Elf32_Word p_type; // Segment type
|
{
|
||||||
Elf32_Off p_offset; // File offset
|
DT_NULL = 0,
|
||||||
Elf32_Addr p_vaddr; // Virtual address
|
DT_NEEDED = 1,
|
||||||
Elf32_Addr p_paddr; // Physical address
|
DT_PLTRELSZ = 2,
|
||||||
Elf32_Word p_filesz; // File image size
|
DT_PLTGOT = 3,
|
||||||
Elf32_Word p_memsz; // Memory image size
|
DT_HASH = 4,
|
||||||
Elf32_Word p_flags; // Segment flags
|
DT_STRTAB = 5,
|
||||||
Elf32_Word p_align; // Alignment value
|
DT_SYMTAB = 6,
|
||||||
} Elf32_Phdr;
|
DT_RELA = 7,
|
||||||
|
DT_RELASZ = 8,
|
||||||
|
DT_RELAENT = 9,
|
||||||
|
DT_STRSZ = 10,
|
||||||
|
DT_SYMENT = 11,
|
||||||
|
DT_INIT = 12,
|
||||||
|
DT_FINI = 13,
|
||||||
|
DT_SONAME = 14,
|
||||||
|
DT_RPATH = 15,
|
||||||
|
DT_SYMBOLIC = 16,
|
||||||
|
DT_REL = 17,
|
||||||
|
DT_RELSZ = 18,
|
||||||
|
DT_RELENT = 19,
|
||||||
|
DT_PLTREL = 20,
|
||||||
|
DT_DEBUG = 21,
|
||||||
|
DT_TEXTREL = 22,
|
||||||
|
DT_JMPREL = 23,
|
||||||
|
DT_ENCODING = 32,
|
||||||
|
OLD_DT_LOOS = 0x60000000,
|
||||||
|
DT_LOOS = 0x6000000d,
|
||||||
|
DT_HIOS = 0x6ffff000,
|
||||||
|
DT_VALRNGLO = 0x6ffffd00,
|
||||||
|
DT_VALRNGHI = 0x6ffffdff,
|
||||||
|
DT_ADDRRNGLO = 0x6ffffe00,
|
||||||
|
DT_ADDRRNGHI = 0x6ffffeff,
|
||||||
|
DT_VERSYM = 0x6ffffff0,
|
||||||
|
DT_RELACOUNT = 0x6ffffff9,
|
||||||
|
DT_RELCOUNT = 0x6ffffffa,
|
||||||
|
DT_FLAGS_1 = 0x6ffffffb,
|
||||||
|
DT_VERDEF = 0x6ffffffc,
|
||||||
|
DT_VERDEFNUM = 0x6ffffffd,
|
||||||
|
DT_VERNEED = 0x6ffffffe,
|
||||||
|
DT_VERNEEDNUM = 0x6fffffff,
|
||||||
|
OLD_DT_HIOS = 0x6fffffff,
|
||||||
|
DT_LOPROC = 0x70000000,
|
||||||
|
DT_HIPROC = 0x7fffffff
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
/* This info is needed when parsing the symbol table */
|
||||||
{
|
enum SymbolBinding
|
||||||
Elf32_Word sh_name; // Name (index into section header string table section)
|
{
|
||||||
Elf32_Word sh_type; // Type
|
STB_LOCAL = 0,
|
||||||
Elf32_Word sh_flags; // Flags
|
STB_GLOBAL = 1,
|
||||||
Elf32_Addr sh_addr; // Address
|
STB_WEAK = 2,
|
||||||
Elf32_Off sh_offset; // File offset
|
STB_LOOS = 10,
|
||||||
Elf32_Word sh_size; // Section size
|
STB_HIOS = 12,
|
||||||
Elf32_Word sh_link; // Section header table index link
|
STB_LOPROC,
|
||||||
Elf32_Word sh_info; // Extra information
|
STB_HIPROC = 0xf
|
||||||
Elf32_Word sh_addralign; // Address alignment
|
};
|
||||||
Elf32_Word sh_entsize; // Section entry size
|
|
||||||
} Elf32_Shdr;
|
|
||||||
|
|
||||||
typedef struct
|
enum SymbolType
|
||||||
{
|
{
|
||||||
Elf32_Addr r_offset; // Offset of relocation
|
STT_NOTYPE = 0,
|
||||||
Elf32_Word r_info; // Symbol table index and type
|
STT_OBJECT = 1,
|
||||||
} Elf32_Rel;
|
STT_FUNC = 2,
|
||||||
|
STT_SECTION = 3,
|
||||||
|
STT_FILE = 4,
|
||||||
|
STT_COMMON = 5,
|
||||||
|
STT_TLS = 6,
|
||||||
|
STT_LOOS = 10,
|
||||||
|
STT_HIOS = 12,
|
||||||
|
STT_LOPROC,
|
||||||
|
STT_HIPROC = 0xf
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
/* These constants define the permissions on sections in the program
|
||||||
{
|
header, p_flags. */
|
||||||
Elf32_Word st_name; // Name - index into string table
|
enum PermissionFlag
|
||||||
Elf32_Addr st_value; // Symbol value
|
{
|
||||||
Elf32_Word st_size; // Symbol size
|
PF_R = 0x4,
|
||||||
unsigned char st_info; // Type and binding
|
PF_W = 0x2,
|
||||||
unsigned char st_other; // Visibility
|
PF_X = 0x1
|
||||||
Elf32_Half st_shndx; // Section header index
|
};
|
||||||
} Elf32_Sym;
|
|
||||||
|
|
||||||
enum
|
/* sh_type */
|
||||||
{
|
enum SectionHeaderType
|
||||||
ET_NONE = 0, // No file type
|
{
|
||||||
ET_REL = 1, // Relocatable file
|
SHT_NULL = 0,
|
||||||
ET_EXEC = 2, // Executable file
|
SHT_PROGBITS = 1,
|
||||||
ET_DYN = 3, // Shared object file
|
SHT_SYMTAB = 2,
|
||||||
ET_CORE = 4, // Core file
|
SHT_STRTAB = 3,
|
||||||
};
|
SHT_RELA = 4,
|
||||||
|
SHT_HASH = 5,
|
||||||
|
SHT_DYNAMIC = 6,
|
||||||
|
SHT_NOTE = 7,
|
||||||
|
SHT_NOBITS = 8,
|
||||||
|
SHT_REL = 9,
|
||||||
|
SHT_SHLIB = 10,
|
||||||
|
SHT_DYNSYM = 11,
|
||||||
|
SHT_NUM = 12,
|
||||||
|
SHT_LOPROC = 0x70000000,
|
||||||
|
SHT_HIPROC = 0x7fffffff,
|
||||||
|
SHT_LOUSER = 0x80000000,
|
||||||
|
SHT_HIUSER = 0xffffffff
|
||||||
|
};
|
||||||
|
|
||||||
|
/* sh_flags */
|
||||||
|
enum SectionHeaderFlag
|
||||||
|
{
|
||||||
|
SHF_WRITE = 0x1,
|
||||||
|
SHF_ALLOC = 0x2,
|
||||||
|
SHF_EXECINSTR = 0x4,
|
||||||
|
SHF_RELA_LIVEPATCH = 0x00100000,
|
||||||
|
SHF_RO_AFTER_INIT = 0x00200000,
|
||||||
|
SHF_MASKPROC = 0xf0000000
|
||||||
|
};
|
||||||
|
|
||||||
|
/* special section indexes */
|
||||||
|
enum SpecialSectionIndex
|
||||||
|
{
|
||||||
|
SHN_UNDEF = 0,
|
||||||
|
SHN_LORESERVE = 0xff00,
|
||||||
|
SHN_LOPROC = 0xff00,
|
||||||
|
SHN_HIPROC = 0xff1f,
|
||||||
|
SHN_LOOS = 0xff20,
|
||||||
|
SHN_HIOS = 0xff3f,
|
||||||
|
SHN_ABS = 0xfff1,
|
||||||
|
SHN_COMMON = 0xfff2,
|
||||||
|
SHN_HIRESERVE = 0xffff
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum ElfIdentIndex
|
||||||
{
|
{
|
||||||
ET_ARM = 40 // ARM architecture
|
EI_MAG0 = 0, /* e_ident[] indexes */
|
||||||
};
|
EI_MAG1 = 1,
|
||||||
|
EI_MAG2 = 2,
|
||||||
|
EI_MAG3 = 3,
|
||||||
|
EI_CLASS = 4,
|
||||||
|
EI_DATA = 5,
|
||||||
|
EI_VERSION = 6,
|
||||||
|
EI_OSABI = 7,
|
||||||
|
EI_PAD = 8
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum ElfClass
|
||||||
{
|
{
|
||||||
EV_NONE = 0, // Invalid version
|
ELFCLASSNONE = 0, /* EI_CLASS */
|
||||||
EV_CURRENT = 1 // Current version
|
ELFCLASS32 = 1,
|
||||||
};
|
ELFCLASS64 = 2,
|
||||||
|
ELFCLASSNUM = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ElfData
|
||||||
|
{
|
||||||
|
ELFDATANONE = 0, /* e_ident[EI_DATA] */
|
||||||
|
ELFDATA2LSB = 1,
|
||||||
|
ELFDATA2MSB = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ElfVersion
|
||||||
|
{
|
||||||
|
EV_NONE = 0, /* e_version, EI_VERSION */
|
||||||
|
EV_CURRENT = 1,
|
||||||
|
EV_NUM = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ElfOsAbi
|
||||||
|
{
|
||||||
|
ELFOSABI_NONE = 0,
|
||||||
|
ELFOSABI_LINUX =3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define ELF_MAGIC "\177ELF"
|
/*
|
||||||
|
* Notes used in ET_CORE. Architectures export some of the arch register sets
|
||||||
|
* using the corresponding note types via the PTRACE_GETREGSET and
|
||||||
|
* PTRACE_SETREGSET requests.
|
||||||
|
*/
|
||||||
|
enum NoteType
|
||||||
|
{
|
||||||
|
NT_PRSTATUS = 1,
|
||||||
|
NT_PRFPREG = 2,
|
||||||
|
NT_PRPSINFO = 3,
|
||||||
|
NT_TASKSTRUCT = 4,
|
||||||
|
NT_AUXV = 6,
|
||||||
|
/*
|
||||||
|
* Note to userspace developers: size of NT_SIGINFO note may increase
|
||||||
|
* in the future to accomodate more fields, don't assume it is fixed!
|
||||||
|
*/
|
||||||
|
NT_SIGINFO = 0x53494749,
|
||||||
|
NT_FILE = 0x46494c45,
|
||||||
|
NT_PRXFPREG = 0x46e62b7f, /* copied from gdb5.1/include/elf/common.h */
|
||||||
|
NT_PPC_VMX = 0x100, /* PowerPC Altivec/VMX registers */
|
||||||
|
NT_PPC_SPE = 0x101, /* PowerPC SPE/EVR registers */
|
||||||
|
NT_PPC_VSX = 0x102, /* PowerPC VSX registers */
|
||||||
|
NT_PPC_TAR = 0x103, /* Target Address Register */
|
||||||
|
NT_PPC_PPR = 0x104, /* Program Priority Register */
|
||||||
|
NT_PPC_DSCR = 0x105, /* Data Stream Control Register */
|
||||||
|
NT_PPC_EBB = 0x106, /* Event Based Branch Registers */
|
||||||
|
NT_PPC_PMU = 0x107, /* Performance Monitor Registers */
|
||||||
|
NT_PPC_TM_CGPR = 0x108, /* TM checkpointed GPR Registers */
|
||||||
|
NT_PPC_TM_CFPR = 0x109, /* TM checkpointed FPR Registers */
|
||||||
|
NT_PPC_TM_CVMX = 0x10a, /* TM checkpointed VMX Registers */
|
||||||
|
NT_PPC_TM_CVSX = 0x10b, /* TM checkpointed VSX Registers */
|
||||||
|
NT_PPC_TM_SPR = 0x10c, /* TM Special Purpose Registers */
|
||||||
|
NT_PPC_TM_CTAR = 0x10d, /* TM checkpointed Target Address Register */
|
||||||
|
NT_PPC_TM_CPPR = 0x10e, /* TM checkpointed Program Priority Register */
|
||||||
|
NT_PPC_TM_CDSCR = 0x10f, /* TM checkpointed Data Stream Control Register */
|
||||||
|
NT_PPC_PKEY = 0x110, /* Memory Protection Keys registers */
|
||||||
|
NT_386_TLS = 0x200, /* i386 TLS slots (struct user_desc) */
|
||||||
|
NT_386_IOPERM = 0x201, /* x86 io permission bitmap (1=deny) */
|
||||||
|
NT_X86_XSTATE = 0x202, /* x86 extended state using xsave */
|
||||||
|
NT_S390_HIGH_GPRS = 0x300, /* s390 upper register halves */
|
||||||
|
NT_S390_TIMER = 0x301, /* s390 timer register */
|
||||||
|
NT_S390_TODCMP = 0x302, /* s390 TOD clock comparator register */
|
||||||
|
NT_S390_TODPREG = 0x303, /* s390 TOD programmable register */
|
||||||
|
NT_S390_CTRS = 0x304, /* s390 control registers */
|
||||||
|
NT_S390_PREFIX = 0x305, /* s390 prefix register */
|
||||||
|
NT_S390_LAST_BREAK = 0x306, /* s390 breaking event address */
|
||||||
|
NT_S390_SYSTEM_CALL = 0x307, /* s390 system call restart data */
|
||||||
|
NT_S390_TDB = 0x308, /* s390 transaction diagnostic block */
|
||||||
|
NT_S390_VXRS_LOW = 0x309, /* s390 vector registers 0-15 upper half */
|
||||||
|
NT_S390_VXRS_HIGH = 0x30a, /* s390 vector registers 16-31 */
|
||||||
|
NT_S390_GS_CB = 0x30b, /* s390 guarded storage registers */
|
||||||
|
NT_S390_GS_BC = 0x30c, /* s390 guarded storage broadcast control block */
|
||||||
|
NT_S390_RI_CB = 0x30d, /* s390 runtime instrumentation */
|
||||||
|
NT_ARM_VFP = 0x400, /* ARM VFP/NEON registers */
|
||||||
|
NT_ARM_TLS = 0x401, /* ARM TLS register */
|
||||||
|
NT_ARM_HW_BREAK = 0x402, /* ARM hardware breakpoint registers */
|
||||||
|
NT_ARM_HW_WATCH = 0x403, /* ARM hardware watchpoint registers */
|
||||||
|
NT_ARM_SYSTEM_CALL = 0x404, /* ARM system call number */
|
||||||
|
NT_ARM_SVE = 0x405, /* ARM Scalable Vector Extension registers */
|
||||||
|
NT_ARC_V2 = 0x600, /* ARCv2 accumulator/extra registers */
|
||||||
|
NT_VMCOREDD = 0x700, /* Vmcore Device Dump Note */
|
||||||
|
NT_MIPS_DSP = 0x800, /* MIPS DSP ASE registers */
|
||||||
|
NT_MIPS_FP_MODE = 0x801, /* MIPS floating-point mode */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kEIdentSize = 0x10;
|
||||||
|
static const byte_t kElfMagic[sizeof(uint32_t)] = {0x7f, 'E', 'L', 'F'};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
ELFDATANONE = 0, // Invalid data encoding
|
|
||||||
ELFDATA2LSB = 1, // Little endian
|
|
||||||
ELFDATA2MSB = 2, // Big endian
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
inline byte_t get_elf_st_bind(byte_t st_info) { return st_info >> 4; }
|
||||||
{
|
inline byte_t get_elf_st_type(byte_t st_info) { return st_info & 0xf; }
|
||||||
PT_NULL = 0, // Unused
|
inline byte_t get_elf_st_info(byte_t st_bind, byte_t st_type) { return (st_type & 0xf) | ((st_bind & 0xf) << 4);}
|
||||||
PT_LOAD = 1, // Loadable segment
|
|
||||||
PT_DYNAMIC = 2, // Dynamic linking information
|
|
||||||
PT_INTERP = 3, // Interpreter
|
|
||||||
PT_NOTE = 4, // Auxiliary information
|
|
||||||
PT_SHLIB = 5, // Reserved
|
|
||||||
PT_PHDR = 6 // Program header table
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
/* The following are used with relocations */
|
||||||
{
|
#define ELF32_R_SYM(x) ((x) >> 8)
|
||||||
PF_R = 4, // Read flag
|
#define ELF32_R_TYPE(x) ((x) & 0xff)
|
||||||
PF_W = 2, // Write flag
|
|
||||||
PF_X = 1, // Execute flag
|
|
||||||
PF_OS_SHARED = 0x100000, // OS-specific
|
|
||||||
PF_CTRSDK = 0x80000000, // Set in CTRSDK ELF Text segments
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||||
{
|
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
|
||||||
SHN_LORESERVE = 0xFF00,
|
}
|
||||||
SHN_HIRESERVE = 0xFFFF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
struct Elf32_Dyn
|
||||||
{
|
{
|
||||||
SHT_NULL = 0, // Inactive
|
int32_t d_tag;
|
||||||
SHT_PROGBITS = 1, // Program defined information
|
union{
|
||||||
SHT_SYMTAB = 2, // Symbol table section
|
int32_t d_val;
|
||||||
SHT_STRTAB = 3, // String table section
|
uint32_t d_ptr;
|
||||||
SHT_RELA = 4, // Relocation section with addends
|
} d_un;
|
||||||
SHT_HASH = 5, // Symbol hash table section
|
};
|
||||||
SHT_DYNAMIC = 6, // Dynamic section
|
|
||||||
SHT_NOTE = 7, // Note section
|
|
||||||
SHT_NOBITS = 8, // No space section
|
|
||||||
SHT_REL = 9, // Relation section without addends
|
|
||||||
SHT_SHLIB = 10, // Reserved
|
|
||||||
SHT_DYNSYM = 11, // Dynamic symbol table section
|
|
||||||
SHT_NUM = 12, // Number of section types
|
|
||||||
SHT_LOPROC = 0x70000000, // Reserved range for processor
|
|
||||||
SHT_ARM_EXIDX = 0x70000001, // ARM exception index table
|
|
||||||
SHT_HIPROC = 0x7fffffff, // Specific section header types
|
|
||||||
SHT_LOUSER = 0x80000000, // Reserved range for application
|
|
||||||
SHT_HIUSER = 0xffffffff // Specific indexes
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
struct Elf64_Dyn
|
||||||
{
|
{
|
||||||
SHF_WRITE = 1, // Writable section
|
int64_t d_tag; /* entry tag value */
|
||||||
SHF_ALLOC = 2, // Loadable section
|
union {
|
||||||
SHF_EXECINSTR = 4, // Executable section
|
uint64_t d_val;
|
||||||
SHF_MASKPROC = 0xf0000000, // Processor-specific
|
uint64_t d_ptr;
|
||||||
};
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
struct Elf32_Rel
|
||||||
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
{
|
||||||
#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t))
|
uint32_t r_offset;
|
||||||
|
uint32_t r_info;
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
struct Elf64_Rel
|
||||||
{
|
{
|
||||||
R_ARM_NONE = 0,
|
uint64_t r_offset; /* Location at which to apply the action */
|
||||||
R_ARM_PC24 = 1,
|
uint64_t r_info; /* index and type of relocation */
|
||||||
R_ARM_ABS32 = 2,
|
};
|
||||||
R_ARM_REL32 = 3,
|
|
||||||
R_ARM_THM_CALL = 10,
|
|
||||||
R_ARM_PLT32 = 27,
|
|
||||||
R_ARM_CALL = 28,
|
|
||||||
R_ARM_JUMP24 = 29,
|
|
||||||
R_ARM_TARGET1 = 38,
|
|
||||||
R_ARM_TARGET2 = 41,
|
|
||||||
R_ARM_PREL31 = 42,
|
|
||||||
R_ARM_THM_JUMP11 = 102,
|
|
||||||
R_ARM_THM_JUMP8 = 103
|
|
||||||
};
|
|
||||||
|
|
||||||
// Symbol scope
|
struct Elf32_Rela
|
||||||
enum
|
{
|
||||||
{
|
uint32_t r_offset;
|
||||||
STB_LOCAL = 0,
|
uint32_t r_info;
|
||||||
STB_GLOBAL = 1,
|
int32_t r_addend;
|
||||||
STB_WEAK = 2
|
};
|
||||||
};
|
|
||||||
|
|
||||||
#define ELF32_ST_BIND(i) (((unsigned char)(i)) >> 4)
|
struct Elf64_Rela
|
||||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
{
|
||||||
|
uint64_t r_offset; /* Location at which to apply the action */
|
||||||
|
uint64_t r_info; /* index and type of relocation */
|
||||||
|
int64_t r_addend; /* Constant addend used to compute value */
|
||||||
|
};
|
||||||
|
|
||||||
// Symbol type
|
struct Elf32_Sym
|
||||||
enum
|
{
|
||||||
{
|
uint32_t st_name;
|
||||||
STT_NOTYPE = 0,
|
uint32_t st_value;
|
||||||
STT_OBJECT = 1,
|
uint32_t st_size;
|
||||||
STT_FUNC = 2
|
byte_t st_info;
|
||||||
};
|
byte_t st_other;
|
||||||
|
uint16_t st_shndx;
|
||||||
|
};
|
||||||
|
|
||||||
// Symbol visibility
|
struct Elf64_Sym
|
||||||
enum
|
{
|
||||||
{
|
uint32_t st_name; /* Symbol name, index in string tbl */
|
||||||
STV_DEFAULT = 0,
|
byte_t st_info; /* Type and binding attributes */
|
||||||
STV_INTERNAL = 1,
|
byte_t st_other; /* No defined meaning, 0 */
|
||||||
STV_HIDDEN = 2,
|
uint16_t st_shndx; /* Associated section index */
|
||||||
STV_PROTECTED = 3
|
uint64_t st_value; /* Value of the symbol */
|
||||||
};
|
uint64_t st_size; /* Associated symbol size */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf32_Ehdr
|
||||||
|
{
|
||||||
|
byte_t e_ident[elf::kEIdentSize];
|
||||||
|
uint16_t e_type;
|
||||||
|
uint16_t e_machine;
|
||||||
|
uint32_t e_version;
|
||||||
|
uint32_t e_entry; /* Entry point */
|
||||||
|
uint32_t e_phoff;
|
||||||
|
uint32_t e_shoff;
|
||||||
|
uint32_t e_flags;
|
||||||
|
uint16_t e_ehsize;
|
||||||
|
uint16_t e_phentsize;
|
||||||
|
uint16_t e_phnum;
|
||||||
|
uint16_t e_shentsize;
|
||||||
|
uint16_t e_shnum;
|
||||||
|
uint16_t e_shstrndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Ehdr
|
||||||
|
{
|
||||||
|
byte_t e_ident[elf::kEIdentSize]; /* ELF "magic number" */
|
||||||
|
uint16_t e_type;
|
||||||
|
uint16_t e_machine;
|
||||||
|
uint32_t e_version;
|
||||||
|
uint64_t e_entry; /* Entry point virtual address */
|
||||||
|
uint64_t e_phoff; /* Program header table file offset */
|
||||||
|
uint64_t e_shoff; /* Section header table file offset */
|
||||||
|
uint32_t e_flags;
|
||||||
|
uint16_t e_ehsize;
|
||||||
|
uint16_t e_phentsize;
|
||||||
|
uint16_t e_phnum;
|
||||||
|
uint16_t e_shentsize;
|
||||||
|
uint16_t e_shnum;
|
||||||
|
uint16_t e_shstrndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf32_Phdr
|
||||||
|
{
|
||||||
|
uint32_t p_type;
|
||||||
|
uint32_t p_offset;
|
||||||
|
uint32_t p_vaddr;
|
||||||
|
uint32_t p_paddr;
|
||||||
|
uint32_t p_filesz;
|
||||||
|
uint32_t p_memsz;
|
||||||
|
uint32_t p_flags;
|
||||||
|
uint32_t p_align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Phdr
|
||||||
|
{
|
||||||
|
uint32_t p_type;
|
||||||
|
uint32_t p_flags;
|
||||||
|
uint64_t p_offset; /* Segment file offset */
|
||||||
|
uint64_t p_vaddr; /* Segment virtual address */
|
||||||
|
uint64_t p_paddr; /* Segment physical address */
|
||||||
|
uint64_t p_filesz; /* Segment size in file */
|
||||||
|
uint64_t p_memsz; /* Segment size in memory */
|
||||||
|
uint64_t p_align; /* Segment alignment, file & memory */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf32_Shdr
|
||||||
|
{
|
||||||
|
uint32_t sh_name;
|
||||||
|
uint32_t sh_type;
|
||||||
|
uint32_t sh_flags;
|
||||||
|
uint32_t sh_addr;
|
||||||
|
uint32_t sh_offset;
|
||||||
|
uint32_t sh_size;
|
||||||
|
uint32_t sh_link;
|
||||||
|
uint32_t sh_info;
|
||||||
|
uint32_t sh_addralign;
|
||||||
|
uint32_t sh_entsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Shdr
|
||||||
|
{
|
||||||
|
uint32_t sh_name; /* Section name, index in string tbl */
|
||||||
|
uint32_t sh_type; /* Type of section */
|
||||||
|
uint64_t sh_flags; /* Miscellaneous section attributes */
|
||||||
|
uint64_t sh_addr; /* Section virtual addr at execution */
|
||||||
|
uint64_t sh_offset; /* Section file offset */
|
||||||
|
uint64_t sh_size; /* Size of section in bytes */
|
||||||
|
uint32_t sh_link; /* Index of another section */
|
||||||
|
uint32_t sh_info; /* Additional section information */
|
||||||
|
uint64_t sh_addralign; /* Section alignment */
|
||||||
|
uint64_t sh_entsize; /* Entry size if section holds table */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note header in a PT_NOTE section */
|
||||||
|
struct Elf32_Nhdr
|
||||||
|
{
|
||||||
|
uint32_t n_namesz; /* Name size */
|
||||||
|
uint32_t n_descsz; /* Content size */
|
||||||
|
uint32_t n_type; /* Content type */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note header in a PT_NOTE section */
|
||||||
|
struct Elf64_Nhdr
|
||||||
|
{
|
||||||
|
uint32_t n_namesz; /* Name size */
|
||||||
|
uint32_t n_descsz; /* Content size */
|
||||||
|
uint32_t n_type; /* Content type */
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,70 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <fnd/types.h>
|
|
||||||
|
|
||||||
namespace nn
|
|
||||||
{
|
|
||||||
namespace hac
|
|
||||||
{
|
|
||||||
namespace elf
|
|
||||||
{
|
|
||||||
enum SpecialSectionIndex
|
|
||||||
{
|
|
||||||
SHN_UNDEF,
|
|
||||||
SHN_LORESERVE = 0xFF00,
|
|
||||||
SHN_LOPROC = 0xFF00,
|
|
||||||
SHN_HIPROC = 0xFF1F,
|
|
||||||
SHN_LOOS,
|
|
||||||
SHN_HIOS = 0xFF3F,
|
|
||||||
SHN_ABS = 0xFFF1,
|
|
||||||
SHN_COMMON,
|
|
||||||
SHN_HIRESERVE = 0xFFFF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SymbolType
|
|
||||||
{
|
|
||||||
STT_NOTYPE,
|
|
||||||
STT_OBJECT,
|
|
||||||
STT_FUNC,
|
|
||||||
STT_SECTION,
|
|
||||||
STT_FILE,
|
|
||||||
STT_LOOS = 10,
|
|
||||||
STT_HIOS = 12,
|
|
||||||
STT_LOPROC,
|
|
||||||
STT_HIPROC = 0xF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SymbolBinding
|
|
||||||
{
|
|
||||||
STB_LOCAL,
|
|
||||||
STB_GLOBAL,
|
|
||||||
STB_WEAK,
|
|
||||||
STB_LOOS = 10,
|
|
||||||
STB_HIOS = 12,
|
|
||||||
STB_LOPROC,
|
|
||||||
STB_HIPROC = 0xF
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma pack(push,1)
|
|
||||||
struct sElfSymbol32Bit
|
|
||||||
{
|
|
||||||
le_uint32_t name;
|
|
||||||
le_uint32_t value;
|
|
||||||
le_uint32_t size;
|
|
||||||
le_uint32_t info;
|
|
||||||
le_uint32_t other;
|
|
||||||
le_uint32_t special_section_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sElfSymbol64Bit
|
|
||||||
{
|
|
||||||
le_uint32_t name;
|
|
||||||
byte_t info;
|
|
||||||
byte_t other;
|
|
||||||
le_uint16_t special_section_index;
|
|
||||||
le_uint64_t value;
|
|
||||||
le_uint64_t size;
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,37 +23,38 @@ bool ElfSymbolParser::operator!=(const ElfSymbolParser& other) const
|
||||||
void ElfSymbolParser::parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit)
|
void ElfSymbolParser::parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit)
|
||||||
{
|
{
|
||||||
//printf("ElfSymbolParser::parseData()");
|
//printf("ElfSymbolParser::parseData()");
|
||||||
size_t dynSymSize = is64Bit ? sizeof(nn::hac::sElfSymbol64Bit) : sizeof(nn::hac::sElfSymbol32Bit);
|
size_t dynSymSize = is64Bit ? sizeof(fnd::Elf64_Sym) : sizeof(fnd::Elf32_Sym);
|
||||||
|
|
||||||
sElfSymbol symbol;
|
sElfSymbol symbol;
|
||||||
for (size_t i = 0; i < dyn_sym_size; i += dynSymSize)
|
for (size_t i = 0; i < dyn_sym_size; i += dynSymSize)
|
||||||
{
|
{
|
||||||
//printf("pos %x\n", i);
|
|
||||||
|
|
||||||
uint32_t name_pos;
|
uint32_t name_pos;
|
||||||
|
|
||||||
if (is64Bit)
|
if (is64Bit)
|
||||||
{
|
{
|
||||||
name_pos = ((nn::hac::sElfSymbol64Bit*)(dyn_sym + i))->name.get();
|
name_pos = le_word(((fnd::Elf64_Sym*)(dyn_sym + i))->st_name);
|
||||||
symbol.shn_index = (nn::hac::elf::SpecialSectionIndex)((nn::hac::sElfSymbol64Bit*)(dyn_sym + i))->special_section_index.get();
|
symbol.shn_index = le_hword(((fnd::Elf64_Sym*)(dyn_sym + i))->st_shndx);
|
||||||
symbol.symbol_type = (nn::hac::elf::SymbolType)((((nn::hac::sElfSymbol64Bit*)(dyn_sym + i))->info) & nn::hac::elf::STT_HIPROC);
|
symbol.symbol_type = fnd::elf::get_elf_st_type(((fnd::Elf64_Sym*)(dyn_sym + i))->st_info);
|
||||||
symbol.symbol_binding = (nn::hac::elf::SymbolBinding)(((((nn::hac::sElfSymbol64Bit*)(dyn_sym + i))->info) >> 4) & nn::hac::elf::STB_HIPROC);
|
symbol.symbol_binding = fnd::elf::get_elf_st_bind(((fnd::Elf64_Sym*)(dyn_sym + i))->st_info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
name_pos = ((nn::hac::sElfSymbol64Bit*)(dyn_sym + i))->name.get();
|
name_pos = le_word(((fnd::Elf32_Sym*)(dyn_sym + i))->st_name);
|
||||||
symbol.shn_index = (nn::hac::elf::SpecialSectionIndex)((nn::hac::sElfSymbol32Bit*)(dyn_sym + i))->special_section_index.get();
|
symbol.shn_index = le_hword(((fnd::Elf32_Sym*)(dyn_sym + i))->st_shndx);
|
||||||
symbol.symbol_type = (nn::hac::elf::SymbolType)((((nn::hac::sElfSymbol32Bit*)(dyn_sym + i))->info.get()) & nn::hac::elf::STT_HIPROC);
|
symbol.symbol_type = fnd::elf::get_elf_st_type(((fnd::Elf32_Sym*)(dyn_sym + i))->st_info);
|
||||||
symbol.symbol_binding = (nn::hac::elf::SymbolBinding)(((((nn::hac::sElfSymbol32Bit*)(dyn_sym + i))->info.get()) >> 4) & nn::hac::elf::STB_HIPROC);
|
symbol.symbol_binding = fnd::elf::get_elf_st_bind(((fnd::Elf32_Sym*)(dyn_sym + i))->st_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_pos >= dyn_str_size)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Out of bounds symbol name offset");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; dyn_str[name_pos] == 0x00 && name_pos < dyn_str_size; name_pos++);
|
for (; dyn_str[name_pos] == 0x00 && name_pos < dyn_str_size; name_pos++);
|
||||||
|
|
||||||
//printf("name_pos = 0x%x\n", name_pos);
|
|
||||||
symbol.name = std::string((char*)&dyn_str[name_pos]);
|
symbol.name = std::string((char*)&dyn_str[name_pos]);
|
||||||
mSymbolList.addElement(symbol);
|
mSymbolList.addElement(symbol);
|
||||||
}
|
}
|
||||||
//printf("ElfSymbolParser::parseData() end\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnd::List<ElfSymbolParser::sElfSymbol>& ElfSymbolParser::getSymbolList() const
|
const fnd::List<ElfSymbolParser::sElfSymbol>& ElfSymbolParser::getSymbolList() const
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/List.h>
|
#include <fnd/List.h>
|
||||||
#include <nn/hac/elf.h>
|
#include <fnd/elf.h>
|
||||||
|
|
||||||
class ElfSymbolParser
|
class ElfSymbolParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct sElfSymbol
|
struct sElfSymbol
|
||||||
{
|
{
|
||||||
nn::hac::elf::SpecialSectionIndex shn_index;
|
uint16_t shn_index;
|
||||||
nn::hac::elf::SymbolType symbol_type;
|
byte_t symbol_type;
|
||||||
nn::hac::elf::SymbolBinding symbol_binding;
|
byte_t symbol_binding;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
void operator=(const sElfSymbol& other)
|
void operator=(const sElfSymbol& other)
|
||||||
|
@ -42,6 +42,7 @@ public:
|
||||||
|
|
||||||
const fnd::List<sElfSymbol>& getSymbolList() const;
|
const fnd::List<sElfSymbol>& getSymbolList() const;
|
||||||
private:
|
private:
|
||||||
|
const std::string kModuleName = "ElfSymbolParser";
|
||||||
|
|
||||||
// data
|
// data
|
||||||
fnd::List<sElfSymbol> mSymbolList;
|
fnd::List<sElfSymbol> mSymbolList;
|
||||||
|
|
|
@ -177,30 +177,30 @@ void RoMetadataProcess::displayRoMetaData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* RoMetadataProcess::getSectionIndexStr(nn::hac::elf::SpecialSectionIndex shn_index) const
|
const char* RoMetadataProcess::getSectionIndexStr(uint16_t shn_index) const
|
||||||
{
|
{
|
||||||
const char* str;
|
const char* str;
|
||||||
switch (shn_index)
|
switch (shn_index)
|
||||||
{
|
{
|
||||||
case (nn::hac::elf::SHN_UNDEF):
|
case (fnd::elf::SHN_UNDEF):
|
||||||
str = "UNDEF";
|
str = "UNDEF";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_LOPROC):
|
case (fnd::elf::SHN_LOPROC):
|
||||||
str = "LOPROC";
|
str = "LOPROC";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_HIPROC):
|
case (fnd::elf::SHN_HIPROC):
|
||||||
str = "HIPROC";
|
str = "HIPROC";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_LOOS):
|
case (fnd::elf::SHN_LOOS):
|
||||||
str = "LOOS";
|
str = "LOOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_HIOS):
|
case (fnd::elf::SHN_HIOS):
|
||||||
str = "HIOS";
|
str = "HIOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_ABS):
|
case (fnd::elf::SHN_ABS):
|
||||||
str = "ABS";
|
str = "ABS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::SHN_COMMON):
|
case (fnd::elf::SHN_COMMON):
|
||||||
str = "COMMON";
|
str = "COMMON";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -210,36 +210,36 @@ const char* RoMetadataProcess::getSectionIndexStr(nn::hac::elf::SpecialSectionIn
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* RoMetadataProcess::getSymbolTypeStr(nn::hac::elf::SymbolType symbol_type) const
|
const char* RoMetadataProcess::getSymbolTypeStr(byte_t symbol_type) const
|
||||||
{
|
{
|
||||||
const char* str;
|
const char* str;
|
||||||
switch (symbol_type)
|
switch (symbol_type)
|
||||||
{
|
{
|
||||||
case (nn::hac::elf::STT_NOTYPE):
|
case (fnd::elf::STT_NOTYPE):
|
||||||
str = "NOTYPE";
|
str = "NOTYPE";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_OBJECT):
|
case (fnd::elf::STT_OBJECT):
|
||||||
str = "OBJECT";
|
str = "OBJECT";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_FUNC):
|
case (fnd::elf::STT_FUNC):
|
||||||
str = "FUNC";
|
str = "FUNC";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_SECTION):
|
case (fnd::elf::STT_SECTION):
|
||||||
str = "SECTION";
|
str = "SECTION";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_FILE):
|
case (fnd::elf::STT_FILE):
|
||||||
str = "FILE";
|
str = "FILE";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_LOOS):
|
case (fnd::elf::STT_LOOS):
|
||||||
str = "LOOS";
|
str = "LOOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_HIOS):
|
case (fnd::elf::STT_HIOS):
|
||||||
str = "HIOS";
|
str = "HIOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_LOPROC):
|
case (fnd::elf::STT_LOPROC):
|
||||||
str = "LOPROC";
|
str = "LOPROC";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STT_HIPROC):
|
case (fnd::elf::STT_HIPROC):
|
||||||
str = "HIPROC";
|
str = "HIPROC";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -249,30 +249,30 @@ const char* RoMetadataProcess::getSymbolTypeStr(nn::hac::elf::SymbolType symbol_
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* RoMetadataProcess::getSymbolBindingStr(nn::hac::elf::SymbolBinding symbol_binding) const
|
const char* RoMetadataProcess::getSymbolBindingStr(byte_t symbol_binding) const
|
||||||
{
|
{
|
||||||
const char* str;
|
const char* str;
|
||||||
switch (symbol_binding)
|
switch (symbol_binding)
|
||||||
{
|
{
|
||||||
case (nn::hac::elf::STB_LOCAL):
|
case (fnd::elf::STB_LOCAL):
|
||||||
str = "LOCAL";
|
str = "LOCAL";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_GLOBAL):
|
case (fnd::elf::STB_GLOBAL):
|
||||||
str = "GLOBAL";
|
str = "GLOBAL";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_WEAK):
|
case (fnd::elf::STB_WEAK):
|
||||||
str = "WEAK";
|
str = "WEAK";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_LOOS):
|
case (fnd::elf::STB_LOOS):
|
||||||
str = "LOOS";
|
str = "LOOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_HIOS):
|
case (fnd::elf::STB_HIOS):
|
||||||
str = "HIOS";
|
str = "HIOS";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_LOPROC):
|
case (fnd::elf::STB_LOPROC):
|
||||||
str = "LOPROC";
|
str = "LOPROC";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::elf::STB_HIPROC):
|
case (fnd::elf::STB_HIPROC):
|
||||||
str = "HIPROC";
|
str = "HIPROC";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -62,7 +62,7 @@ private:
|
||||||
void importApiList();
|
void importApiList();
|
||||||
void displayRoMetaData();
|
void displayRoMetaData();
|
||||||
|
|
||||||
const char* getSectionIndexStr(nn::hac::elf::SpecialSectionIndex shn_index) const;
|
const char* getSectionIndexStr(uint16_t shn_index) const;
|
||||||
const char* getSymbolTypeStr(nn::hac::elf::SymbolType symbol_type) const;
|
const char* getSymbolTypeStr(byte_t symbol_type) const;
|
||||||
const char* getSymbolBindingStr(nn::hac::elf::SymbolBinding symbol_binding) const;
|
const char* getSymbolBindingStr(byte_t symbol_binding) const;
|
||||||
};
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#define VER_MAJOR 1
|
#define VER_MAJOR 1
|
||||||
#define VER_MINOR 0
|
#define VER_MINOR 0
|
||||||
#define VER_PATCH 2
|
#define VER_PATCH 3
|
||||||
#define AUTHORS "jakcron"
|
#define AUTHORS "jakcron"
|
Loading…
Reference in a new issue