stephenrkell / liballocs

Meta-level run-time services for Unix processes... a.k.a. dragging Unix into the 1980s
http://humprog.org/~stephen/research/liballocs
Other
213 stars 25 forks source link

Internal documentation is lacking #61

Open stephenrkell opened 2 years ago

stephenrkell commented 2 years ago

The whole codebase really needs me to do a brain dump in each .c file, explaining what goes on in each. A lot of non-obvious things 'obvious to me' are not stated anywhere.

For the 'overall' picture, the Onward! 2015 paper in theory covers this, but it doesn't do a great job and some of its details are outdated. It may be time to write a follow-up paper focusing on experience. Some things I can think of are the following.

stephenrkell commented 2 years ago

Another one:

stephenrkell commented 2 years ago

More

stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago
stephenrkell commented 2 years ago

Could make a point that all this reentrancy-avoidance is about 'stratifying' (in the sense of Bracha and Ungar) the memory allocation system in the process. We rely on the lower stratum, i.e. the kernel's page allocator.

stephenrkell commented 2 years ago

The old mallochooks approach of separating out reentrant calls to a sideline malloc requires on free() a way to tell apart sideline from mainline chunks, because reentrant alloc contexts needn't be reentrant free contexts. The new way is to avoid the reentrancy.

stephenrkell commented 1 year ago

Another thing to mention: the mess with aliases (see comments in allocs-cflags). Neither GRP_COMDAT section groups nor global-symbol uniquing do the right thing in the presence of aliases; they can (respectively) discard aliases or break (de-alias) them.

stephenrkell commented 1 year ago

Another thing was my aborted attempt at using strongly connected components (SCCs) in the DWARF to generate a stable notion of type identity for recursive types that may be defined independently multiple times. This 'obviously' doesn't work because of opaque structs and the like, since these cut the graph in different ways in different contexts.

For some reason, this has turned out not to be important, even though for a while I was sure it would be.

stephenrkell commented 1 year ago

Continuing the 'opaque struct' thing: one could perhaps relate it to the idea in C that "types have no linkage" and the definition of "compatible type". I think the short summary (check this!) is that there's no nominal distinction of struct types having 'the same' definition... whereas in effect we are forced to create one. The reason it doesn't bite is that "independently multiple times" doesn't happen [much].

stephenrkell commented 1 year ago

Continuing again: we are only forced to create one if we let synthetic file/line information creep into the summary codes of the struct or any of its (transitive) constituents. But we might be able to avoid that. Need to re-check what I did about this.

stephenrkell commented 1 year ago

Another topic is the fun with gdb had during chain loading... e.g. how gdb will scan the .dynamic section in the file on disk, and only access inferior memory in very specific places. It even caches the location of _dl_debug_state, leading to our amusing gyrations in allocsld. I guess this belongs with discussion of the ELF zygote in libdlbind... overall, the mechanisms can support the dynamism but the assumptions made by tools sometimes partially undo that support.

stephenrkell commented 10 months ago

One gyration (in allocsld/chain.c) involves padding .interp so we can later clobber it (if 'requested') or else simply later swap argv[0] to point to the inferior ld.so (if 'invoked'), to avoid the real (inferior) ld.so getting confused about its own name on disk.

But the main point continuing the preceding: you could call it a 'disk--memory assumption', about what is equal between a file's image on disk and its image in memory. One cannot simply overwrite stuff in memory and have that take precedence. That's why we end up clobbering _dl_debug_state in the inferior ld.so, so that instead of a no-op it calls our own _dl_debug_state which is the One True debugger-please-breakpoint-me function. The debugger will call the thing whose address it looks up on disk, not in memory.

It's not 100% clear that we need the debugger-please-breakpoint-me function to be in allocsld.so, if gdb will reliably find the real (inferior) ld.so when it looks.

stephenrkell commented 9 months ago

The n-way comparison of indexers mooted in #67 could be a good experimental addition to a new paper.