diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index 42ea9d0..0000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "recommendations": [
- "ms-vscode.cpptools",
- "wayou.vscode-todo-highlight",
- "gruntfuggly.todo-tree",
- "13xforever.language-x86-64-assembly",
- "webfreak.debug",
- "zixuanwang.linkerscript",
- "maziac.hex-hover-converter",
- "cschlosser.doxdocgen",
- "streetsidesoftware.code-spell-checker"
- ]
-}
\ No newline at end of file
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp
index 8167f5f..37eb70a 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp
@@ -217,8 +217,10 @@ EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info)
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
- fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
- elf->num, elf->size, elf->entsize, elf->shndx);
+ mb2binfo.Kernel.Symbols.Num = elf->num;
+ mb2binfo.Kernel.Symbols.EntSize = elf->entsize;
+ mb2binfo.Kernel.Symbols.Shndx = elf->shndx;
+ mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections;
break;
}
case MULTIBOOT_TAG_TYPE_APM:
diff --git a/Core/Memory/PageMapIndexer.cpp b/Core/Memory/PageMapIndexer.cpp
index d16212e..76bec31 100644
--- a/Core/Memory/PageMapIndexer.cpp
+++ b/Core/Memory/PageMapIndexer.cpp
@@ -19,27 +19,27 @@
namespace Memory
{
- Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
- {
+ Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
+ {
#if defined(a64)
- uintptr_t Address = VirtualAddress;
- Address >>= 12;
- this->PTEIndex = Address & 0x1FF;
- Address >>= 9;
- this->PDEIndex = Address & 0x1FF;
- Address >>= 9;
- this->PDPTEIndex = Address & 0x1FF;
- Address >>= 9;
- this->PMLIndex = Address & 0x1FF;
+ uintptr_t Address = VirtualAddress;
+ Address >>= 12;
+ this->PTEIndex = Address & 0x1FF;
+ Address >>= 9;
+ this->PDEIndex = Address & 0x1FF;
+ Address >>= 9;
+ this->PDPTEIndex = Address & 0x1FF;
+ Address >>= 9;
+ this->PMLIndex = Address & 0x1FF;
#elif defined(a32)
- uintptr_t Address = VirtualAddress;
- Address >>= 12;
- this->PTEIndex = Address & 0x3FF;
- Address >>= 10;
- this->PDEIndex = Address & 0x3FF;
- Address >>= 10;
- this->PDPTEIndex = Address & 0x3FF;
+ uintptr_t Address = VirtualAddress;
+ Address >>= 12;
+ this->PTEIndex = Address & 0x3FF;
+ Address >>= 10;
+ this->PDEIndex = Address & 0x3FF;
+ Address >>= 10;
+ this->PDPTEIndex = Address & 0x3FF;
#elif defined(aa64)
#endif
- }
+ }
}
diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp
index b9a0cfc..d7c93cc 100644
--- a/Core/Memory/PhysicalMemoryManager.cpp
+++ b/Core/Memory/PhysicalMemoryManager.cpp
@@ -377,63 +377,100 @@ namespace Memory
TotalMemory = MemorySize;
FreeMemory = MemorySize;
- void *LargestFreeMemorySegment = nullptr;
- uint64_t LargestFreeMemorySegmentSize = 0;
+ size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
+ uintptr_t BitmapAddress = 0x0;
+ size_t BitmapAddressSize = 0;
+
+ uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase;
+ uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size;
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
{
if (bInfo.Memory.Entry[i].Type == Usable)
{
- if (bInfo.Memory.Entry[i].Length > LargestFreeMemorySegmentSize)
+ uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress;
+ uintptr_t RegionSize = bInfo.Memory.Entry[i].Length;
+
+ /* We don't want to use 0 as a memory address. */
+ if (RegionAddress == 0x0)
+ continue;
+
+ if ((BitmapSize + 0x100) > RegionSize)
{
- /* We don't want to use 0 as a memory address. */
- if (bInfo.Memory.Entry[i].BaseAddress == 0x0)
- continue;
-
- LargestFreeMemorySegment = (void *)bInfo.Memory.Entry[i].BaseAddress;
- LargestFreeMemorySegmentSize = bInfo.Memory.Entry[i].Length;
-
- debug("Largest free memory segment: %llp (%lldMB)",
- (void *)bInfo.Memory.Entry[i].BaseAddress,
- TO_MB(bInfo.Memory.Entry[i].Length));
+ debug("Region %p-%p (%dMB) is too small for bitmap.",
+ (void *)RegionAddress,
+ (void *)(RegionAddress + RegionSize),
+ TO_MB(RegionSize));
+ continue;
}
+
+ BitmapAddress = RegionAddress;
+ BitmapAddressSize = RegionSize;
+
+ if (RegionAddress >= KernelStart && KernelEnd <= (RegionAddress + RegionSize))
+ {
+ BitmapAddress = KernelEnd;
+ BitmapAddressSize = RegionSize - (KernelEnd - RegionAddress);
+ }
+
+ if ((BitmapSize + 0x100) > BitmapAddressSize)
+ {
+ debug("Region %p-%p (%dMB) is too small for bitmap.",
+ (void *)RegionAddress,
+ (void *)(RegionAddress + BitmapAddressSize),
+ TO_MB(BitmapAddressSize));
+ continue;
+ }
+
+ for (size_t i = 0; i < MAX_MODULES; i++)
+ {
+ uintptr_t ModuleStart = (uintptr_t)bInfo.Modules[i].Address;
+ uintptr_t ModuleEnd = (uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size;
+
+ if (ModuleStart == 0x0)
+ break;
+
+ if (RegionAddress >= ModuleStart && ModuleEnd <= (RegionAddress + RegionSize))
+ {
+ BitmapAddress = ModuleEnd;
+ BitmapAddressSize = RegionSize - (ModuleEnd - RegionAddress);
+ }
+ }
+
+ if ((BitmapSize + 0x100) > BitmapAddressSize)
+ {
+ debug("Region %p-%p (%dMB) is too small for bitmap.",
+ (void *)BitmapAddress,
+ (void *)(BitmapAddress + BitmapAddressSize),
+ TO_MB(BitmapAddressSize));
+ continue;
+ }
+
+ debug("Found free memory for bitmap: %p (%dMB)",
+ (void *)BitmapAddress,
+ TO_MB(BitmapAddressSize));
+ break;
}
}
- if (LargestFreeMemorySegment == nullptr)
+ if (BitmapAddress == 0x0)
{
error("No free memory found!");
CPU::Stop();
}
/* TODO: Read swap config and make the configure the bitmap size correctly */
- size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
- debug("Initializing Bitmap at %llp-%llp (%lld Bytes)",
- LargestFreeMemorySegment,
- (void *)((uintptr_t)LargestFreeMemorySegment + BitmapSize),
+ debug("Initializing Bitmap at %p-%p (%d Bytes)",
+ BitmapAddress,
+ (void *)(BitmapAddress + BitmapSize),
BitmapSize);
PageBitmap.Size = BitmapSize;
- PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegment;
+ PageBitmap.Buffer = (uint8_t *)BitmapAddress;
for (size_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
- debug("Reserving pages...");
- this->ReservePages(0, TO_PAGES(bInfo.Memory.Size));
- debug("Unreserving usable pages...");
-
- for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
- {
- if (bInfo.Memory.Entry[i].Type == Usable)
- this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress, TO_PAGES(bInfo.Memory.Entry[i].Length));
- }
-
- debug("Reserving pages for SMP...");
- this->ReservePage((void *)0x0); /* Trampoline stack, gdt, idt, etc... */
- this->ReservePages((void *)0x2000, 4); /* TRAMPOLINE_START */
-
- debug("Reserving bitmap pages...");
- this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size));
+ ReserveEssentials();
}
Physical::Physical() {}
diff --git a/Core/Memory/ReserveEssentials.cpp b/Core/Memory/ReserveEssentials.cpp
new file mode 100644
index 0000000..71d00fb
--- /dev/null
+++ b/Core/Memory/ReserveEssentials.cpp
@@ -0,0 +1,122 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+
+#include
+#ifdef DEBUG
+#include
+#endif
+
+#if defined(a64)
+#include "../../Architecture/amd64/acpi.hpp"
+#elif defined(a32)
+#include "../../Architecture/i386/acpi.hpp"
+#elif defined(aa64)
+#endif
+
+#include "../../kernel.h"
+
+namespace Memory
+{
+ __no_sanitize("alignment") void Physical::ReserveEssentials()
+ {
+ debug("Reserving pages...");
+ /* The bootloader won't give us the entire mapping, so we
+ reserve everything and then unreserve the usable pages. */
+ this->ReservePages(0, TO_PAGES(bInfo.Memory.Size));
+ debug("Unreserving usable pages...");
+
+ for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
+ {
+ if (bInfo.Memory.Entry[i].Type == Usable)
+ this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress, TO_PAGES(bInfo.Memory.Entry[i].Length));
+ }
+
+ debug("Reserving 0x0-0xFFFFF range...");
+ // this->ReservePage((void *)0x0); /* Trampoline stack, gdt, idt, etc... */
+ // this->ReservePages((void *)0x2000, 4); /* TRAMPOLINE_START */
+
+ /* Reserve the lower part of memory. (0x0-0xFFFFF)
+ This includes: BIOS, EBDA, VGA, SMP, etc...
+ https://wiki.osdev.org/Memory_Map_(x86)
+ */
+ this->ReservePages((void *)0x0, TO_PAGES(0xFFFFF));
+
+ debug("Reserving bitmap region %#lx-%#lx...", PageBitmap.Buffer, (void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size));
+ this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size));
+
+ debug("Reserving kernel physical region %#lx-%#lx...", bInfo.Kernel.PhysicalBase, (void *)((uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size));
+ this->ReservePages(bInfo.Kernel.PhysicalBase, TO_PAGES(bInfo.Kernel.Size));
+
+ debug("Reserving kernel file and symbols...");
+ if (bInfo.Kernel.FileBase)
+ this->ReservePages(bInfo.Kernel.FileBase, TO_PAGES(bInfo.Kernel.Size));
+
+ if (bInfo.Kernel.Symbols.Num && bInfo.Kernel.Symbols.EntSize && bInfo.Kernel.Symbols.Shndx)
+ this->ReservePages((void *)bInfo.Kernel.Symbols.Sections, TO_PAGES(bInfo.Kernel.Symbols.Num * bInfo.Kernel.Symbols.EntSize));
+
+ debug("Reserving kernel modules...");
+
+ for (uint64_t i = 0; i < MAX_MODULES; i++)
+ {
+ if (bInfo.Modules[i].Address == 0x0)
+ continue;
+
+ debug("Reserving module %s (%#lx-%#lx)...", bInfo.Modules[i].CommandLine,
+ bInfo.Modules[i].Address, (void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size));
+
+ this->ReservePages((void *)bInfo.Modules[i].Address, TO_PAGES(bInfo.Modules[i].Size));
+ }
+
+#if defined(a86)
+ debug("Reserving RSDT region %#lx-%#lx...", bInfo.RSDP, (void *)((uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo)));
+ this->ReservePages(bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo)));
+
+ ACPI::ACPI::ACPIHeader *ACPIPtr = nullptr;
+ bool XSDT = false;
+
+ if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
+ {
+ ACPIPtr = (ACPI::ACPI::ACPIHeader *)(bInfo.RSDP->XSDTAddress);
+ XSDT = true;
+ }
+ else
+ ACPIPtr = (ACPI::ACPI::ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
+
+ debug("Reserving RSDT...");
+ this->ReservePages((void *)bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo)));
+
+ size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4));
+ debug("Reserving %d ACPI tables...", TableSize);
+
+ for (size_t t = 0; t < TableSize; t++)
+ {
+ // TODO: Should I be concerned about unaligned memory access?
+ ACPI::ACPI::ACPIHeader *SDTHdr = nullptr;
+ if (XSDT)
+ SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 8)));
+ else
+ SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4)));
+
+ this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length));
+ }
+
+#elif defined(aa64)
+#endif
+ }
+}
diff --git a/Core/Symbols.cpp b/Core/Symbols.cpp
index 089b23c..2dd0cb0 100644
--- a/Core/Symbols.cpp
+++ b/Core/Symbols.cpp
@@ -25,6 +25,105 @@
namespace SymbolResolver
{
+ const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
+ {
+ Symbols::SymbolTable Result{0, (char *)""};
+ for (int64_t i = 0; i < this->TotalEntries; i++)
+ if (this->SymTable[i].Address <= Address && this->SymTable[i].Address > Result.Address)
+ Result = this->SymTable[i];
+ return Result.FunctionName;
+ }
+
+ void Symbols::AddSymbol(uintptr_t Address, const char *Name)
+ {
+ if (this->TotalEntries >= 0x10000)
+ {
+ error("Symbol table is full");
+ return;
+ }
+
+ this->SymTable[this->TotalEntries].Address = Address;
+ strcpy(this->SymTable[this->TotalEntries].FunctionName, Name);
+ this->TotalEntries++;
+ }
+
+ __no_sanitize("alignment") void Symbols::AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections)
+ {
+ if (this->TotalEntries >= 0x10000)
+ {
+ error("Symbol table is full");
+ return;
+ }
+
+ Elf64_Shdr *ElfSections = (Elf64_Shdr *)(Sections);
+ Elf64_Sym *ElfSymbols = nullptr;
+ char *strtab = nullptr;
+
+ for (uint64_t i = 0; i < Num; i++)
+ switch (ElfSections[i].sh_type)
+ {
+ case SHT_SYMTAB:
+ ElfSymbols = (Elf64_Sym *)(Sections + ElfSections[i].sh_offset);
+ this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
+ if (this->TotalEntries >= 0x10000)
+ this->TotalEntries = 0x10000 - 1;
+
+ debug("Symbol table found, %d entries", this->TotalEntries);
+ break;
+ case SHT_STRTAB:
+ if (Shndx == i)
+ {
+ debug("String table found, %d entries", ElfSections[i].sh_size);
+ }
+ else
+ {
+ strtab = (char *)(Sections + ElfSections[i].sh_offset);
+ debug("String table found, %d entries", ElfSections[i].sh_size);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (ElfSymbols != nullptr && strtab != nullptr)
+ {
+ int64_t Index, MinimumIndex;
+ for (int64_t i = 0; i < this->TotalEntries - 1; i++)
+ {
+ MinimumIndex = i;
+ for (Index = i + 1; Index < this->TotalEntries; Index++)
+ if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
+ MinimumIndex = Index;
+ Elf64_Sym tmp = ElfSymbols[MinimumIndex];
+ ElfSymbols[MinimumIndex] = ElfSymbols[i];
+ ElfSymbols[i] = tmp;
+ }
+
+ while (ElfSymbols[0].st_value == 0)
+ {
+ if (this->TotalEntries <= 0)
+ break;
+ ElfSymbols++;
+ this->TotalEntries--;
+ }
+
+ if (this->TotalEntries <= 0)
+ {
+ error("Symbol table is empty");
+ return;
+ }
+
+ trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable)));
+ for (uintptr_t i = 0, g = this->TotalEntries; i < g; i++)
+ {
+ this->SymTable[i].Address = ElfSymbols[i].st_value;
+ this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
+
+ // debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName);
+ }
+ }
+ }
+
Symbols::Symbols(uintptr_t ImageAddress)
{
if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false)
@@ -76,8 +175,8 @@ namespace SymbolResolver
if (ElfSymbols != nullptr && strtab != nullptr)
{
- uintptr_t Index, MinimumIndex;
- for (uintptr_t i = 0; i < this->TotalEntries - 1; i++)
+ int64_t Index, MinimumIndex;
+ for (int64_t i = 0; i < this->TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < this->TotalEntries; Index++)
@@ -106,26 +205,4 @@ namespace SymbolResolver
}
Symbols::~Symbols() {}
-
- const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
- {
- Symbols::SymbolTable Result{0, (char *)""};
- for (uintptr_t i = 0; i < this->TotalEntries; i++)
- if (this->SymTable[i].Address <= Address && this->SymTable[i].Address > Result.Address)
- Result = this->SymTable[i];
- return Result.FunctionName;
- }
-
- NIF void Symbols::AddSymbol(uintptr_t Address, const char *Name)
- {
- if (this->TotalEntries >= 0x10000)
- {
- error("Symbol table is full");
- return;
- }
-
- this->SymTable[this->TotalEntries].Address = Address;
- strcpy(this->SymTable[this->TotalEntries].FunctionName, Name);
- this->TotalEntries++;
- }
}
diff --git a/Kernel.cpp b/Kernel.cpp
index d769410..ba7df81 100644
--- a/Kernel.cpp
+++ b/Kernel.cpp
@@ -271,6 +271,15 @@ EXTERNC NIF void Main()
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
+ if (KernelSymbolTable->GetTotalEntries() == 0 &&
+ bInfo.Kernel.Symbols.Num &&
+ bInfo.Kernel.Symbols.EntSize &&
+ bInfo.Kernel.Symbols.Shndx)
+ KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num,
+ bInfo.Kernel.Symbols.EntSize,
+ bInfo.Kernel.Symbols.Shndx,
+ bInfo.Kernel.Symbols.Sections);
+
KPrint("Reading Kernel Parameters");
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
diff --git a/Makefile b/Makefile
index 6c30374..9a52f10 100644
--- a/Makefile
+++ b/Makefile
@@ -55,7 +55,7 @@ LDFLAGS := -Wl,-Map kernel.map -shared -nostdlib -nodefaultlibs -nolibc
WARNCFLAG = -Wall -Wextra \
-Wfloat-equal -Wpointer-arith -Wcast-align \
-Wredundant-decls -Winit-self -Wswitch-default \
- -Wstrict-overflow=5 -Wconversion -w
+ -Wstrict-overflow=5 -Wconversion
# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
CFLAGS := \
diff --git a/include/boot/binfo.h b/include/boot/binfo.h
index 9b32263..5985df2 100644
--- a/include/boot/binfo.h
+++ b/include/boot/binfo.h
@@ -133,6 +133,14 @@ struct BootInfo
void *FileBase;
char CommandLine[256];
__UINT64_TYPE__ Size;
+
+ struct KernelSymbolInfo
+ {
+ __UINT32_TYPE__ Num;
+ __UINT32_TYPE__ EntSize;
+ __UINT32_TYPE__ Shndx;
+ __UINTPTR_TYPE__ Sections;
+ } Symbols;
} Kernel;
struct BootloaderInfo
diff --git a/include/memory.hpp b/include/memory.hpp
index c6874de..b01e520 100644
--- a/include/memory.hpp
+++ b/include/memory.hpp
@@ -468,6 +468,8 @@ namespace Memory
uint64_t PageBitmapIndex = 0;
Bitmap PageBitmap;
+ void ReserveEssentials();
+
public:
Bitmap GetPageBitmap() { return PageBitmap; }
diff --git a/include/symbols.hpp b/include/symbols.hpp
index 6214a7a..e580f37 100644
--- a/include/symbols.hpp
+++ b/include/symbols.hpp
@@ -30,14 +30,16 @@ namespace SymbolResolver
};
SymbolTable SymTable[0x10000];
- uintptr_t TotalEntries = 0;
+ int64_t TotalEntries = 0;
void *Image;
public:
+ size_t GetTotalEntries() { return this->TotalEntries; }
void *GetImage() { return this->Image; }
- Symbols(uintptr_t ImageAddress);
- ~Symbols();
const char *GetSymbolFromAddress(uintptr_t Address);
void AddSymbol(uintptr_t Address, const char *Name);
+ void AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections);
+ Symbols(uintptr_t ImageAddress);
+ ~Symbols();
};
}