diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index a6748ceb20..a9ab0605ce 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -676,3 +676,8 @@ LIBSYSTEMD_241 { global: sd_bus_close_unref; } LIBSYSTEMD_240; + +LIBSYSTEMD_243 { +global: + sd_bus_object_vtable_format; +} LIBSYSTEMD_241; diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index d9fc25605a..ce2cb94bde 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -1701,7 +1701,8 @@ struct sd_bus_vtable_original { #define VTABLE_ELEMENT_SIZE sizeof(struct sd_bus_vtable) static int vtable_features(const sd_bus_vtable *vtable) { - if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL) + if (vtable[0].x.start.element_size < VTABLE_ELEMENT_SIZE || + !vtable[0].x.start.vtable_format_reference) return 0; return vtable[0].x.start.features; } @@ -1928,6 +1929,9 @@ fail: return r; } +/* This symbol exists solely to tell the linker that the "new" vtable format is used. */ +_public_ const unsigned sd_bus_object_vtable_format = 242; + _public_ int sd_bus_add_object_vtable( sd_bus *bus, sd_bus_slot **slot, diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h index 8a73ef0503..e3804e203c 100644 --- a/src/systemd/sd-bus-vtable.h +++ b/src/systemd/sd-bus-vtable.h @@ -52,6 +52,15 @@ enum { _SD_BUS_VTABLE_PARAM_NAMES = 1 << 0, }; +extern const unsigned sd_bus_object_vtable_format; + +/* Note: unused areas in the sd_bus_vtable[] array must be initalized to 0. The stucture contains an embedded + * union, and the compiler is NOT required to initalize the unused areas of the union when the rest of the + * structure is initalized. Normally the array is defined as read-only data, in which case the linker places + * it in the BSS section, which is always fully initalized, so this is not a concern. But if the array is + * created on the stack or on the heap, care must be taken to initalize the unused areas, for examply by + * first memsetting the whole region to zero before filling the data in. */ + struct sd_bus_vtable { /* Please do not initialize this structure directly, use the * macros below instead */ @@ -62,6 +71,7 @@ struct sd_bus_vtable { struct { size_t element_size; uint64_t features; + const unsigned *vtable_format_reference; } start; struct { const char *member; @@ -93,7 +103,8 @@ struct sd_bus_vtable { .x = { \ .start = { \ .element_size = sizeof(sd_bus_vtable), \ - .features = _SD_BUS_VTABLE_PARAM_NAMES \ + .features = _SD_BUS_VTABLE_PARAM_NAMES, \ + .vtable_format_reference = &sd_bus_object_vtable_format, \ }, \ }, \ } diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py index 357cce8e44..2510809452 100755 --- a/src/test/generate-sym-test.py +++ b/src/test/generate-sym-test.py @@ -6,18 +6,22 @@ for header in sys.argv[2:]: print('#include "{}"'.format(header.split('/')[-1])) print(''' -void* functions[] = {''') +const void* symbols[] = {''') for line in open(sys.argv[1]): match = re.search('^ +([a-zA-Z0-9_]+);', line) if match: - print(' {},'.format(match.group(1))) + s = match.group(1) + if s == 'sd_bus_object_vtable_format': + print(f' &{s},') + else: + print(f' {s},') print('''}; int main(void) { unsigned i; - for (i = 0; i < sizeof(functions)/sizeof(void*); i++) - printf("%p\\n", functions[i]); + for (i = 0; i < sizeof(symbols)/sizeof(void*); i++) + printf("%p\\n", symbols[i]); return 0; }''')