Skip to content

Copy relocations against liballocs cause problems #175

@stephenrkell

Description

@stephenrkell

liballocs wants to export some of its data structures, like pageindex, for direct use by client code in other objects, including the executable. It also wants to provide inline functions that use these data structures, usable also from external objects.

This has long been tricky. In particular we disable some inline functions... from liballocs.h:

/* HACK HACK HACKETY HACK: we want our fast-path functions to be inlined.
 * However, there's a linking problem: we reference pageindex which is a protected
 * symbol. From an executable that is a client of liballocs, under the small code
 * model, the linker won't let us reference this symbol (copy-reloc'ing a protected
 * symbol is a recipe for trouble, which ld.bfd sensibly does not allow). So we
 * don't inline this function from such clients. We use a hacky method for identifying
 * them: non-PIC code. This BREAKS small-model PIE executables -- use -mcmodel=large
 * if you want a PIE executable that is a client of liballocs. FIXME: I'm not actually
 * sure that sensible things happen under the large code model -- more experimentation
 * required.
 */
#if defined(__PIC__) || defined(__code_model_large__)
inline 
struct liballocs_err *
__liballocs_get_alloc_info
	(const void *obj, 
	struct allocator **out_allocator,
	const void **out_alloc_start,
	unsigned long *out_alloc_size_bytes, 
	struct uniqtype **out_alloc_uniqtype, 
	const void **out_alloc_site)
{
...
}

The main issue is that for performance reasons within liballocs, pageindex has protected visibility, i.e. liballocs's definition of that symbol is always the one referenced. Therefore outside liballocs, we also want to reference the copy inside liballocs -- but this is only possible under the large code model, since this avoids trying to copy-relocate it (which will provoke an error).

We also have __liballocs_pageindex which is an alias. The idea here is that external code will use this alias and avoid requiring the pageindex declaration polluting its namespace. Probably pageindex should therefore be hidden, not protected, but for now it reiamns protected.

Interestingly, under this arrangement and using __liballocs_pageindex, the alloca test case works fine with GCC but not with Clang... with Clang it seems to generate a copy relocation against __liballocs_pageindex whereas GCC does not. This reveals that of course __liballocs_pageindex is just as broken by copy-relocation as pageindex was. There is also now the failure case where one of them gets overridden or copy-reloc'd but the other doesn't, breaking the intended aliasing. Perhaps pageindex should just be a macro, defined only within liballocs.

I am going to investigate the GCC-vs-Clang issue here and post more.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions