While sizes (and possibly positions) of the symbol table related symbols (and as a result other ones) are expected to change from linking pass 1 to pass 2, no such change should happen anymore from pass 2 to pass 3, or else the internally recorded symbol table wouldn't represent the ELF or PE/COFF ones.
For comparing to be actually useful, i.e. most notably also covering the last of the arrays emitted, symbol sizes need establishing. Make use of the xen/linkage.h machinery to achieve that. Suggested-by: Roger Pau Monné <[email protected]> Signed-off-by: Jan Beulich <[email protected]> --- Likely other ports also want to add such checking. Really it would be nice if we could properly abstract out shared parts of the linking steps. RFC: Aiui this can't go in as is right now, or we would break building Xen with lld. Further changes are first needed to help the situation there. RFC: I'm all ears towards improvement suggestions in the temporary helper file handling of compare-symbol-tables. Or ideally some approach to avoid the use of a helper file altogether. --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -146,6 +146,7 @@ $(TARGET)-syms: $(objtree)/prelink.o $(o | $(objtree)/tools/symbols $(all_symbols) --sysv --sort $(syms-warn-dup-y) \ > $(dot-target).1.S $(MAKE) $(build)=$(@D) $(dot-target).1.o + $(call compare-symbol-tables, $(dot-target).0.o, $(dot-target).1.o) $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds $< $(build_id_linker) \ $(orphan-handling-y) $(dot-target).1.o -o $@ $(NM) -pa --format=sysv $@ \ @@ -226,6 +227,8 @@ endif | $(objtree)/tools/symbols $(all_symbols) --sysv --sort \ > $(dot-target).1s.S $(MAKE) $(build)=$(@D) .$(@F).1r.o .$(@F).1s.o + $(call compare-symbol-tables, $(dot-target).0r.o, $(dot-target).1r.o) + $(call compare-symbol-tables, $(dot-target).0s.o, $(dot-target).1s.o) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T $(obj)/efi.lds $< \ $(dot-target).1r.o $(dot-target).1s.o $(orphan-handling-y) \ $(note_file_option) -o $@ --- a/xen/scripts/Kbuild.include +++ b/xen/scripts/Kbuild.include @@ -56,6 +56,19 @@ define filechk fi endef +### +# Compare the symbol tables of two object files. As diff's -I option isn't +# standardized, the name difference of the two object files needs abstracting +# out. +define compare-symbol-tables + ln -f $(1) $(@D)/.cst.$$$$; \ + $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(1).sym; \ + ln -f $(1) $(@D)/.cst.$$$$; \ + $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(2).sym; \ + rm -f $(@D)/.cst.$$$$ + diff -u $(1).sym $(2).sym +endef + # as-insn: Check whether assembler supports an instruction. # Usage: cflags-y += $(call as-insn,CC FLAGS,"insn",option-yes,option-no) as-insn = $(if $(shell echo 'void _(void) { asm volatile ( $(2) ); }' \ --- a/xen/tools/symbols.c +++ b/xen/tools/symbols.c @@ -253,17 +253,26 @@ static void read_map(FILE *in) } } -static void output_label(char *label) +static void output_label(const char *label, bool keep) { - if (symbol_prefix_char) - printf(".globl %c%s\n", symbol_prefix_char, label); - else - printf(".globl %s\n", label); - printf("\tALGN\n"); - if (symbol_prefix_char) - printf("%c%s:\n", symbol_prefix_char, label); - else - printf("%s:\n", label); + static bool pending; + + if (pending && !keep) { + printf("END(CURRENT)\n"); + printf("#undef CURRENT\n\n"); + } + + pending = label; + if (!label) + return; + + if (symbol_prefix_char) { + printf("DATA(%c%s, ALGN)\n", symbol_prefix_char, label); + printf("#define CURRENT %c%s\n", symbol_prefix_char, label); + } else { + printf("DATA(%s, ALGN)\n", label); + printf("#define CURRENT %s\n", label); + } } /* uncompress a compressed symbol. When this function is called, the best table @@ -331,22 +340,22 @@ static void write_src(void) return; } - printf("#include <xen/config.h>\n"); + printf("#include <xen/linkage.h>\n"); printf("#if BITS_PER_LONG == 64 && !defined(SYMBOLS_ORIGIN)\n"); printf("#define PTR .quad\n"); - printf("#define ALGN .balign 8\n"); + printf("#define ALGN 8\n"); printf("#else\n"); printf("#define PTR .long\n"); - printf("#define ALGN .balign 4\n"); + printf("#define ALGN 4\n"); printf("#endif\n"); printf("\t.section .rodata, \"a\"\n"); printf("#ifndef SYMBOLS_ORIGIN\n"); printf("#define SYMBOLS_ORIGIN 0\n"); - output_label("symbols_addresses"); + output_label("symbols_addresses", false); printf("#else\n"); - output_label("symbols_offsets"); + output_label("symbols_offsets", true); printf("#endif\n"); for (i = 0, ends = 0; i < table_cnt; i++) { printf("\tPTR\t%#llx - SYMBOLS_ORIGIN\n", table[i].addr); @@ -370,17 +379,15 @@ static void write_src(void) printf("\tPTR\t%#llx - SYMBOLS_ORIGIN\n", table[i].addr + table[i].size); } - printf("\n"); - output_label("symbols_num_addrs"); + output_label("symbols_num_addrs", false); printf("\t.long\t%d\n", table_cnt + ends); - printf("\n"); /* table of offset markers, that give the offset in the compressed stream * every 256 symbols */ markers = malloc(sizeof(*markers) * ((table_cnt + ends + 255) >> 8)); - output_label("symbols_names"); + output_label("symbols_names", false); for (i = 0, off = 0, ends = 0; i < table_cnt; i++) { if (((i + ends) & 0xFF) == 0) markers[(i + ends) >> 8] = off; @@ -404,15 +411,12 @@ static void write_src(void) printf("\t.byte 0\n"); ++off; } - printf("\n"); - output_label("symbols_markers"); + output_label("symbols_markers", false); for (i = 0; i < ((table_cnt + ends + 255) >> 8); i++) printf("\t.long\t%d\n", markers[i]); - printf("\n"); - - output_label("symbols_token_table"); + output_label("symbols_token_table", false); off = 0; for (i = 0; i < 256; i++) { best_idx[i] = off; @@ -420,34 +424,27 @@ static void write_src(void) printf("\t.asciz\t\"%s\"\n", buf); off += strlen(buf) + 1; } - printf("\n"); - output_label("symbols_token_index"); + output_label("symbols_token_index", false); for (i = 0; i < 256; i++) printf("\t.short\t%d\n", best_idx[i]); - printf("\n"); - if (!sort_by_name) { - free(markers); - return; - } - - output_label("symbols_num_names"); - printf("\t.long\t%d\n", table_cnt); - printf("\n"); - - /* Sorted by original symbol names and type. */ - qsort(table, table_cnt, sizeof(*table), compare_name_orig); - - output_label("symbols_sorted_offsets"); - /* A fixed sized array with two entries: offset in the - * compressed stream (for symbol name), and offset in - * symbols_addresses (or symbols_offset). */ - for (i = 0; i < table_cnt; i++) { - printf("\t.long %u, %u\n", table[i].stream_offset, table[i].addr_idx); + if (sort_by_name) { + output_label("symbols_num_names", false); + printf("\t.long\t%d\n", table_cnt); + + /* Sorted by original symbol names and type. */ + qsort(table, table_cnt, sizeof(*table), compare_name_orig); + + /* A fixed sized array with two entries: offset in the + * compressed stream (for symbol name), and offset in + * symbols_addresses (or symbols_offset). */ + output_label("symbols_sorted_offsets", false); + for (i = 0; i < table_cnt; i++) + printf("\t.long %u, %u\n", table[i].stream_offset, table[i].addr_idx); } - printf("\n"); + output_label(NULL, false); free(markers); }
