Skip to content

Commit

Permalink
Fix snapshot save/load in dynamic-extension
Browse files Browse the repository at this point in the history
On linux I added support that a vtable section can be in
a dynamic library.
  • Loading branch information
meister committed Nov 29, 2024
1 parent 0b6f8ad commit 88550de
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 43 deletions.
23 changes: 12 additions & 11 deletions include/clasp/core/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,26 @@ struct OpenDynamicLibraryInfo {
gctools::clasp_ptr_t _LibraryStart;
gctools::clasp_ptr_t _TextStart;
gctools::clasp_ptr_t _TextEnd;
bool _HasVtableSection;
gctools::clasp_ptr_t _VtableSectionStart;
gctools::clasp_ptr_t _VtableSectionEnd;
OpenDynamicLibraryInfo(const std::string& f, void* h, const SymbolTable& symbol_table, gctools::clasp_ptr_t libstart,
gctools::clasp_ptr_t textStart, gctools::clasp_ptr_t textEnd)
: _Filename(f), _Handle(h), _SymbolTable(symbol_table), _LibraryStart(libstart), _TextStart(textStart),
_TextEnd(textEnd){
gctools::clasp_ptr_t textStart, gctools::clasp_ptr_t textEnd,
bool hasVtableSection,
gctools::clasp_ptr_t vtableSectionStart, gctools::clasp_ptr_t vtableSectionEnd)
: _Filename(f), _Handle(h), _SymbolTable(symbol_table), _LibraryStart(libstart), _TextStart(textStart), _TextEnd(textEnd),
_HasVtableSection(hasVtableSection), _VtableSectionStart(vtableSectionStart), _VtableSectionEnd(vtableSectionEnd) {
// printf("%s:%d:%s filename = %s\n", __FILE__, __LINE__, __FUNCTION__, f.c_str() );
};
virtual LoadableKind loadableKind() const { return Library; };
OpenDynamicLibraryInfo(){};
};

struct ExecutableLibraryInfo : OpenDynamicLibraryInfo {
bool _HasVtableSection;
gctools::clasp_ptr_t _VtableSectionStart;
gctools::clasp_ptr_t _VtableSectionEnd;
ExecutableLibraryInfo(const std::string& f, void* h, const SymbolTable& symbol_table, gctools::clasp_ptr_t libstart,
gctools::clasp_ptr_t textStart, gctools::clasp_ptr_t textEnd, bool hasVtableSection,
gctools::clasp_ptr_t vtableSectionStart, gctools::clasp_ptr_t vtableSectionEnd)
: OpenDynamicLibraryInfo(f, h, symbol_table, libstart, textStart, textEnd), _HasVtableSection(hasVtableSection),
_VtableSectionStart(vtableSectionStart), _VtableSectionEnd(vtableSectionEnd) {
gctools::clasp_ptr_t textStart, gctools::clasp_ptr_t textEnd,
bool hasVtableSection, gctools::clasp_ptr_t vtableSectionStart, gctools::clasp_ptr_t vtableSectionEnd)
: OpenDynamicLibraryInfo(f, h, symbol_table, libstart, textStart, textEnd, hasVtableSection, vtableSectionStart, vtableSectionEnd ) {
#if 0
printf("%s:%d:%s filename = %s\n", __FILE__, __LINE__, __FUNCTION__, f.c_str() );
if (vtableSectionStart==NULL) {
Expand Down Expand Up @@ -215,6 +216,6 @@ DebugInfo& debugInfo();

void executablePath(std::string& name);
void executableTextSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end);
void executableVtableSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end);
void exclusiveVtableSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end);

}; // namespace core
23 changes: 10 additions & 13 deletions src/core/debug_unixes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,23 +304,21 @@ CL_DEFUN void core__walk_loaded_objects() {
}

int elf_startup_loaded_object_callback(struct dl_phdr_info* info, size_t size, void* data) {
// printf("%s:%d:%s Startup registering loaded object %s\n", __FILE__, __LINE__, __FUNCTION__, info->dlpi_name);
// printf("%s:%d:%s --------- Startup registering loaded object %s\n", __FILE__, __LINE__, __FUNCTION__, info->dlpi_name);
core::General_O general;
gctools::clasp_ptr_t vtablePtr = *(gctools::clasp_ptr_t*)&general;
// printf("%s:%d:%s one vtablePtr = %p\n", __FILE__, __LINE__, __FUNCTION__, vtablePtr );
// printf("%s:%d:%s a KNOWN vtablePtr = %p\n", __FILE__, __LINE__, __FUNCTION__, vtablePtr );
ScanInfo* scan_callback_info = (ScanInfo*)data;
bool is_executable = false;
const char* libname;
if (scan_callback_info->_Index == 0 && strlen(info->dlpi_name) == 0) {
libname = getExecutablePath();
is_executable = true;
// printf("%s:%d:%s getExecutablePath() libname %s is_executable = %d\n", __FILE__, __LINE__, __FUNCTION__, libname,
// is_executable );
// printf("%s:%d:%s getExecutablePath() libname %s is_executable = %d\n", __FILE__, __LINE__, __FUNCTION__, libname, is_executable );
} else {
libname = info->dlpi_name;
is_executable = false;
// printf("%s:%d:%s info->dlpi_name libname %s is_executable = %d\n", __FILE__, __LINE__, __FUNCTION__, libname, is_executable
// );
// printf("%s:%d:%s info->dlpi_name libname %s is_executable = %d\n", __FILE__, __LINE__, __FUNCTION__, libname, is_executable );
}
gctools::clasp_ptr_t text_start;
gctools::clasp_ptr_t text_end;
Expand All @@ -335,8 +333,7 @@ int elf_startup_loaded_object_callback(struct dl_phdr_info* info, size_t size, v
if (p_type == PT_LOAD && (info->dlpi_phdr[j].p_flags & 0x1)) { // executable
text_start = (gctools::clasp_ptr_t)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr);
text_end = (gctools::clasp_ptr_t)(text_start + info->dlpi_phdr[j].p_memsz);
// printf("%s:%d:%s text_start = %p text_end = %p\n low = %p high = %p vtablePtr = %p\n", __FILE__, __LINE__,
// __FUNCTION__, (void*)text_start, (void*)text_end, low, high, vtablePtr );
// printf("%s:%d:%s text_start = %p text_end = %p low = %p high = %p\n", __FILE__, __LINE__, __FUNCTION__, (void*)text_start, (void*)text_end, low, high );
}
if (low <= vtablePtr && vtablePtr < high) {
//
Expand All @@ -354,9 +351,9 @@ int elf_startup_loaded_object_callback(struct dl_phdr_info* info, size_t size, v
hasVtableSection = true;
vtableSectionStart = low;
vtableSectionEnd = high;
// printf("%s:%d:%s set vtableSection Start/End = %p/%p\n", __FILE__, __LINE__, __FUNCTION__, low, high );
// printf("%s:%d:%s set vtableSection Start/End = %p/%p\n", __FILE__, __LINE__, __FUNCTION__, low, high );
}
// printf("%s:%d:%s Found vtableSection %p to %p\n", __FILE__, __LINE__, __FUNCTION__, vtableSectionStart, vtableSectionEnd );
// printf("%s:%d:%s Found vtableSection %p to %p\n", __FILE__, __LINE__, __FUNCTION__, vtableSectionStart, vtableSectionEnd );
}
}
// printf("%s:%d:%s About to call add_dynamic_library_using_origin libname = %s is_executable = %d\n", __FILE__, __LINE__,
Expand All @@ -377,8 +374,7 @@ void startup_register_loaded_objects(add_dynamic_library* callback) {
otherwise it uses handle to look up the start of the library. */
void add_dynamic_library_impl(add_dynamic_library* callback, bool is_executable, const std::string& libraryName, bool use_origin,
uintptr_t library_origin, void* handle, gctools::clasp_ptr_t text_start,
gctools::clasp_ptr_t text_end, bool hasVtableSection, gctools::clasp_ptr_t vtableSectionStart,
gctools::clasp_ptr_t vtableSectionEnd) {
gctools::clasp_ptr_t text_end, bool hasVtableSection, gctools::clasp_ptr_t vtableSectionStart, gctools::clasp_ptr_t vtableSectionEnd) {
// printf("%s:%d:%s libraryName = %s is_executable = %d\n", __FILE__, __LINE__, __FUNCTION__, libraryName.c_str(), is_executable
// );
BT_LOG(("Starting to load library: %s\n", libraryName.c_str()));
Expand Down Expand Up @@ -421,7 +417,8 @@ void add_dynamic_library_impl(add_dynamic_library* callback, bool is_executable,
} else {
// printf("%s:%d:%s Creating an OpenDynamicLibraryInfo\n", __FILE__, __LINE__, __FUNCTION__ );
odli =
new OpenDynamicLibraryInfo(libraryName, handle, symbol_table, (gctools::clasp_ptr_t)library_origin, text_start, text_end);
new OpenDynamicLibraryInfo(libraryName, handle, symbol_table, (gctools::clasp_ptr_t)library_origin, text_start, text_end,
hasVtableSection, vtableSectionStart, vtableSectionEnd );
loadable = Library;
}
TrapProblem trap(is_executable, libraryName, odli->loadableKind());
Expand Down
61 changes: 46 additions & 15 deletions src/core/debugger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,18 +199,42 @@ void executablePath(std::string& name) {
}
SIMPLE_ERROR("Could not find the executablePath");
}
void executableVtableSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end) {

void exclusiveVtableSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end) {
WITH_READ_LOCK(debugInfo()._OpenDynamicLibraryMutex);
size_t numberOfVtableRanges = 0;
for (auto& entry : debugInfo()._OpenDynamicLibraryHandles) {
if (entry.second->loadableKind() == Executable) {
ExecutableLibraryInfo* eli = dynamic_cast<ExecutableLibraryInfo*>(entry.second);
start = eli->_VtableSectionStart;
end = eli->_VtableSectionEnd;
if (entry.second->_HasVtableSection) {
// This assumes there is only one vtable section!!!!!!!
start = entry.second->_VtableSectionStart;
end = entry.second->_VtableSectionEnd;
numberOfVtableRanges++;
// printf("%s:%d:%s vtableRange# %lu library: %s vtable section start %p end %p\n", __FILE__, __LINE__, __FUNCTION__, numberOfVtableRanges, entry.first.c_str(), start, end );
}
}
if (numberOfVtableRanges>1) {
printf("%s:%d:%s There can be only one vtable range in the executable or dynamic libraries - if there is more than one then we need to rearrange things and identify the vtable range that contains snapshot save/load-able objects\n", __FILE__, __LINE__, __FUNCTION__);
gctools::wait_for_user_signal("About to exit");
} else if (numberOfVtableRanges==0) {
printf("%s:%d:%s Could not find any vtable sections\n", __FILE__, __LINE__, __FUNCTION__);
gctools::wait_for_user_signal("About to exit");
}
}

CL_DEFUN void core__openDynamicLibraries() {
WITH_READ_LOCK(debugInfo()._OpenDynamicLibraryMutex);
for (auto& entry : debugInfo()._OpenDynamicLibraryHandles) {
printf("%s:%d:%s lib: %s exec %d\n", __FILE__, __LINE__, __FUNCTION__, entry.first.c_str(), entry.second->loadableKind()==Executable );
void* textstart = entry.second->_TextStart;
void* textend = entry.second->_TextEnd;
printf("%s:%d:%s textStart: %p textEnd: %p \n", __FILE__, __LINE__, __FUNCTION__, textstart, textend );
if (entry.second->_HasVtableSection) {
void* start = entry.second->_VtableSectionStart;
void* end = entry.second->_VtableSectionEnd;
printf("%s:%d:%s vtableStart: %p vtableEnd: %p \n", __FILE__, __LINE__, __FUNCTION__, start, end );
// printf("%s:%d:%s start %p end %p\n", __FILE__, __LINE__, __FUNCTION__, start, end );
return;
}
}
SIMPLE_ERROR("Could not find the executableVtableSectionRange");
}

void executableTextSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end) {
Expand All @@ -222,12 +246,14 @@ void executableTextSectionRange(gctools::clasp_ptr_t& start, gctools::clasp_ptr_
return;
}
}
SIMPLE_ERROR("Could not find the executableVtableSectionRange");
SIMPLE_ERROR("Could not find the executableTextSectionRange");
}

bool lookup_address_in_library(gctools::clasp_ptr_t address, gctools::clasp_ptr_t& start, gctools::clasp_ptr_t& end,
std::string& libraryName, bool& executable, uintptr_t& vtableStart, uintptr_t& vtableEnd) {
WITH_READ_LOCK(debugInfo()._OpenDynamicLibraryMutex);
vtableStart = 0;
vtableEnd = 0;
for (auto entry : debugInfo()._OpenDynamicLibraryHandles) {
// printf("%s:%d:%s Looking at entry: %s start: %p end: %p\n", __FILE__, __LINE__, __FUNCTION__,
// entry.second._Filename.c_str(), entry.second._LibraryStart, entry.second._LibraryEnd );
Expand All @@ -238,17 +264,22 @@ bool lookup_address_in_library(gctools::clasp_ptr_t address, gctools::clasp_ptr_
start = eli->_TextStart;
end = eli->_TextEnd;
executable = true;
vtableStart = (uintptr_t)eli->_VtableSectionStart;
vtableEnd = (uintptr_t)eli->_VtableSectionEnd;
if (eli->_HasVtableSection) {
vtableStart = (uintptr_t)eli->_VtableSectionStart;
vtableEnd = (uintptr_t)eli->_VtableSectionEnd;
}
return true;
}
} else if (entry.second->_TextStart <= address && address < entry.second->_TextEnd) {
} else if ((entry.second->_TextStart <= address && address < entry.second->_TextEnd)
|| (entry.second->_HasVtableSection && entry.second->_VtableSectionStart<=address && address<entry.second->_VtableSectionEnd) ) {
libraryName = entry.second->_Filename;
start = entry.second->_TextStart;
end = entry.second->_TextEnd;
executable = false;
vtableStart = 0; // libraries don't have vtables we care about
vtableEnd = 0;
if (entry.second->_HasVtableSection) {
vtableStart = (uintptr_t)entry.second->_VtableSectionStart; // libraries don't have vtables we care about
vtableEnd = (uintptr_t)entry.second->_VtableSectionEnd;
}
return true;
}
}
Expand Down Expand Up @@ -280,8 +311,8 @@ bool library_with_name(const std::string& name, bool isExecutable, std::string&
libraryName = entry.second->_Filename;
start = (uintptr_t)(entry.second->_TextStart);
end = (uintptr_t)(entry.second->_TextEnd);
vtableStart = 0; // (uintptr_t)entry.second->_VtableSectionStart;
vtableEnd = 0; // (uintptr_t)entry.second->_VtableSectionEnd;
vtableStart = (uintptr_t)entry.second->_VtableSectionStart;
vtableEnd = (uintptr_t)entry.second->_VtableSectionEnd;
// printf("%s:%d:%s isExecutable = %d name = %s libraryName = %s\n", __FILE__, __LINE__, __FUNCTION__, isExecutable,
// name.c_str(), libraryName.c_str());
return true;
Expand Down
12 changes: 12 additions & 0 deletions src/gctools/gcFunctions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,18 @@ CL_DEFUN core::T_mv gctools__memory_profile_status() {
core::make_fixnum(allocationSizeCounter), core::make_fixnum(allocationSizeThreshold));
}


CL_DEFUN core::T_sp gctools__object_address(core::General_sp generalObject) {
void* address = (void*)&(*generalObject);
printf("%s:%d:%s address = %p\n", __FILE__, __LINE__, __FUNCTION__, address );
return nil<core::T_O>();
}
CL_DEFUN core::T_sp gctools__vtable_address(core::General_sp generalObject) {
void* vtable_ptr = *(void**)&(*generalObject);
printf("%s:%d:%s vtable pointer = %p\n", __FILE__, __LINE__, __FUNCTION__, vtable_ptr );
return nil<core::T_O>();
}

DOCGROUP(clasp);
CL_DEFUN core::T_sp gctools__stack_depth() {
int z = 0;
Expand Down
17 changes: 13 additions & 4 deletions src/gctools/snapshotSaveLoad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
#include <clasp/llvmo/jit.h>
#include <clasp/gctools/snapshotSaveLoad.h>

// Turn on debugging vtable pointer updates with libraries
//#define DEBUG_ISLLIBRARIES 1


#ifdef _TARGET_OS_LINUX
#include <elf.h>
#endif
Expand Down Expand Up @@ -2586,9 +2590,10 @@ void* snapshot_save_impl(void* data) {

{
DBG_SL_STEP(11, "snapshot_save fixing up vtable pointers\n");
core::lisp_write(fmt::format("Fixup vtable pointers\n"));
gctools::clasp_ptr_t start;
gctools::clasp_ptr_t end;
core::executableVtableSectionRange(start, end);
core::exclusiveVtableSectionRange(start, end);
fixup_vtables_t fixup_vtables(&fixup, (uintptr_t)start, (uintptr_t)end, &islInfo);
walk_snapshot_save_load_objects((ISLHeader_s*)snapshot._Memory->_BufferStart, fixup_vtables);
}
Expand Down Expand Up @@ -3097,8 +3102,10 @@ void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const s
if (fout)
fflush(fout); // flush fout if it's defined. --arguments option was passed
updateRelocationTableAfterLoad(lib, lookup);
//printf("%s:%d:%s Done updateRelocationTableAfterLoad pushing library with name: %s\n", __FILE__, __LINE__, __FUNCTION__, lib._Name.c_str() );
#ifdef DEBUG_ISLLIBRARIES
printf("%s:%d:%s Done updateRelocationTableAfterLoad pushing library with name: %s\n", __FILE__, __LINE__, __FUNCTION__, lib._Name.c_str() );
printf("%s:%d:%s push_back lib: %s start: %p end: %p vtableStart: %p vtableEnd: %p\n",
__FILE__, __LINE__, __FUNCTION__, lib._Name.c_str(), lib._TextStart, lib._TextEnd, (void*)lib._VtableStart, (void*)lib._VtableEnd);
#endif
fixup._ISLLibraries.push_back(lib);
}
Expand All @@ -3119,7 +3126,7 @@ void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const s
DBG_SL("2 snapshot_load fixing up vtable pointers\n");
gctools::clasp_ptr_t start;
gctools::clasp_ptr_t end;
core::executableVtableSectionRange(start, end);
core::exclusiveVtableSectionRange(start, end);
if (start == NULL) {
printf("%s:%d:%s vtable section range start is NULL\n", __FILE__, __LINE__, __FUNCTION__);
}
Expand Down Expand Up @@ -3194,9 +3201,11 @@ void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const s
DBG_SL("6 Allocate objects\n");
{
ISLHeader_s* start_header = reinterpret_cast<ISLHeader_s*>(islbuffer);
#if 0
gctools::clasp_ptr_t startVtables;
gctools::clasp_ptr_t end;
core::executableVtableSectionRange(startVtables, end);
core::exclusiveVtableSectionRange(startVtables, end);
#endif
ISLHeader_s* next_header;
ISLHeader_s* cur_header;

Expand Down

0 comments on commit 88550de

Please sign in to comment.