1

On Windows, the HMODULE returned from LoadLibrary is the base pointer of the loaded DLL.

The shared library I use is a headless version of a game. To save its state, I parse the DLL to locate the .data and .bss sections, add their VAs to the DLL's base address, then copy the right amount of data from each section.

In principle, the same should be doable on Linux. However, I'm stuck on how to get the base address of a dlopen()ed ELF library, since the void* returned from dlopen() is a pointer to the shared library's link_map AFAIK.

How might I accomplish this?

EDIT 1: The "state" of the shared library is the state of all the static variables in it. To save that state, I copy the sections that contain them (.data and .bss) to an alternate buffer (in memory). When I restore that state, I write the alternate buffer's data back to the shared library's .data and .bss.

itzjackyscode
  • 970
  • 9
  • 27
  • 4
    "_To save its state, I parse the DLL to locate the .data and .bss sections_" ... wouldn't it be simpler to add the needed functions to the game library so that it can provide a way of saving/restoring the state via a proper API? – Ted Lyngmo Aug 31 '21 at 22:06
  • Can you clarify exactly what "To save its state" means? Are you attempting to modify a shared library so that when a variable in the library is changed that change is persisted in the library binary? – dbush Aug 31 '21 at 22:40
  • 1
    *In principle, the same should be doable on Linux* In principle, you're lucky that works at all. On any platform. How do you know some of that data doesn't point to other data that in dynamically-allocated memory? Or points within itself and then gets restored to another address for some reason? – Andrew Henle Aug 31 '21 at 22:57
  • @dbush see edit 1. – itzjackyscode Aug 31 '21 at 23:26
  • 1
    This sounds like an XY problem. Are you able to access the source of this library? If so, you should create a pair of functions whose job it is to export/import the library's state to/from a given file. – dbush Sep 01 '21 at 03:01

1 Answers1

3

Read and parse the file /proc/self/maps.

That said, the notion of saving the state of a noncooperating library by dumping its data section is rather questionable. Imagine there is a pointer. It points at some other variable else in the data section. There is no way you can tell it's a pointer - from the standpoint of the controlling program, it's just a word in memory that by pure accident contains a value that corresponds to a valid address. If the library is loaded at some other address and the state is restored, the said pointer won't be valid anymore.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • There are multiple entries associated with every loaded ELF file. Which entry am I looking for? – itzjackyscode Aug 31 '21 at 22:16
  • 1
    The one that's read/writable but not executable. That's data. – Seva Alekseyev Aug 31 '21 at 22:18
  • @itzjackyscode The mechanism proposed in this answer is exceedingly error-prone due to recent changes: https://stackoverflow.com/questions/57761007/why-an-elf-executable-could-have-4-load-segments. The info you seek is readily available via `dl_iterate_phdr` -- see https://stackoverflow.com/a/19485562/50617 – Employed Russian Sep 02 '21 at 03:29
  • Point taken, but in the examples over there, there is still only one RW segment. The API based solution is cleaner, though. – Seva Alekseyev Sep 02 '21 at 14:02