diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-05-25 10:33:12 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-25 10:33:12 -0700 |
commit | 4a211f679cd19207085b2e53c1c6572a47226fc1 (patch) | |
tree | 05be60a3fa9f1f86b753834910e5cb16599733f0 | |
parent | 14952a63ac017687efacf5d1f02de2b35e7e45f7 (diff) | |
download | syslinux-4a211f679cd19207085b2e53c1c6572a47226fc1.tar.gz |
com32r: allow absolute and relative symbols based on regex
Allow relocs.c to sort linker-assigned absolute symbols into true
absolute and relative symbols based on regular expressions.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | com32/MCONFIG | 2 | ||||
-rw-r--r-- | com32/lib/com32.ld | 7 | ||||
-rw-r--r-- | com32/tools/relocs.c | 110 |
3 files changed, 78 insertions, 41 deletions
diff --git a/com32/MCONFIG b/com32/MCONFIG index 2136176d..414011a8 100644 --- a/com32/MCONFIG +++ b/com32/MCONFIG @@ -82,4 +82,4 @@ C_LNXLIBS = $(com32)/libutil/libutil_lnx.a %.c32: %.elf $(OBJCOPY) -O binary $< $@ - $(RELOCS) $< >> $@ + $(RELOCS) $< >> $@ || ( rm -f $@ ; false ) diff --git a/com32/lib/com32.ld b/com32/lib/com32.ld index 41e88da4..f615e82d 100644 --- a/com32/lib/com32.ld +++ b/com32/lib/com32.ld @@ -13,6 +13,7 @@ SECTIONS /* Read-only sections, merged into text segment: */ . = 0; PROVIDE (__executable_start = .); + PROVIDE (_stext = .); .init : { @@ -28,11 +29,12 @@ SECTIONS { KEEP (*(.fini)) } =0x90909090 - PROVIDE (__etext = .); PROVIDE (_etext = .); - PROVIDE (etext = .); + + __rodata_start = .; .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + __rodata_end = .; /* Ensure the __preinit_array_start label is properly aligned. We could instead move the label definition inside the section, but @@ -105,7 +107,6 @@ SECTIONS } . = ALIGN(4); _end = .; - PROVIDE (end = .); /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/com32/tools/relocs.c b/com32/tools/relocs.c index 028ff315..19eb6654 100644 --- a/com32/tools/relocs.c +++ b/com32/tools/relocs.c @@ -1,3 +1,6 @@ +/* + * This file is taken from the Linux kernel and is distributed under GPL v2. + */ #include <stdio.h> #include <stdarg.h> #include <stdlib.h> @@ -9,6 +12,8 @@ #include <byteswap.h> #define USE_BSD #include <endian.h> +#include <regex.h> +#include <sys/types.h> #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static Elf32_Ehdr ehdr; @@ -24,40 +29,60 @@ struct section { }; static struct section *secs; +static void die(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + /* - * Following symbols have been audited. There values are constant and do - * not change if bzImage is loaded at a different physical address than - * the address for which it has been compiled. Don't warn user about + * Following symbols have been audited. Don't warn user about * absolute relocations present w.r.t these symbols. */ -static const char* safe_abs_relocs[] = { - "xen_irq_disable_direct_reloc", - "xen_save_fl_direct_reloc", -}; -static int is_safe_abs_reloc(const char* sym_name) +/* True absolute relocations */ + +static const char safe_abs_regex[] = +"^(__.*_len|__.*_dwords)$"; +static regex_t safe_abs_regex_c; + +static int is_safe_abs_reloc(const char *sym_name) { - int i; + return !regexec(&safe_abs_regex_c, sym_name, 0, NULL, 0); +} - for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) { - if (!strcmp(sym_name, safe_abs_relocs[i])) - /* Match found */ - return 1; - } - if (strncmp(sym_name, "VDSO", 4) == 0) - return 1; - if (strncmp(sym_name, "__crc_", 6) == 0) - return 1; - return 0; +/* These are relative even though the linker marks them absolute */ + +static const char safe_rel_regex[] = +"^(__.*_start|__.*_end|_end|_[se](text|data))$"; +static regex_t safe_rel_regex_c; + +static int is_safe_rel_reloc(const char *sym_name) +{ + return !regexec(&safe_rel_regex_c, sym_name, 0, NULL, 0); } -static void die(char *fmt, ...) +static void regex_init(void) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(1); + char errbuf[128]; + int err; + + err = regcomp(&safe_abs_regex_c, safe_abs_regex, + REG_EXTENDED|REG_NOSUB); + if (err) { + regerror(err, &safe_abs_regex_c, errbuf, sizeof errbuf); + die("%s", errbuf); + } + + err = regcomp(&safe_rel_regex_c, safe_rel_regex, + REG_EXTENDED|REG_NOSUB); + if (err) { + regerror(err, &safe_rel_regex_c, errbuf, sizeof errbuf); + die("%s", errbuf); + } } static const char *sym_type(unsigned type) @@ -404,7 +429,7 @@ static void print_absolute_symbols(void) printf("\n"); } -static void print_absolute_relocs(void) +static int print_absolute_relocs(FILE *f) { int i, printed = 0; @@ -448,18 +473,17 @@ static void print_absolute_relocs(void) * Before warning check if this absolute symbol * relocation is harmless. */ - if (is_safe_abs_reloc(name)) + if (is_safe_abs_reloc(name) || + is_safe_rel_reloc(name)) continue; if (!printed) { - printf("WARNING: Absolute relocations" - " present\n"); - printf("Offset Info Type Sym.Value " - "Sym.Name\n"); + fprintf(f, "Unknown absolute relocations present\n"); + fprintf(f, "Offset Info Type Sym.Value Sym.Name\n"); printed = 1; } - printf("%08x %08x %10s %08x %s\n", + fprintf(f, "%08x %08x %10s %08x %s\n", rel->r_offset, rel->r_info, rel_type(ELF32_R_TYPE(rel->r_info)), @@ -469,7 +493,9 @@ static void print_absolute_relocs(void) } if (printed) - printf("\n"); + fputc('\n', f); + + return printed; } static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) @@ -501,9 +527,10 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; r_type = ELF32_R_TYPE(rel->r_info); /* Don't visit relocations to absolute symbols */ - if (sym->st_shndx == SHN_ABS) { + if (sym->st_shndx == SHN_ABS && + !is_safe_rel_reloc(sym_name(sym_strtab, sym))) continue; - } + switch (r_type) { case R_386_PC32: case R_386_GOTPC: @@ -527,11 +554,14 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) { + (void)rel; (void)sym; reloc_count += 1; } static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) { + (void)sym; + /* Remember the address that needs to be adjusted. */ relocs[reloc_idx++] = rel->r_offset; } @@ -601,6 +631,7 @@ int main(int argc, char **argv) const char *fname; FILE *fp; int i; + int err = 0; show_absolute_syms = 0; show_absolute_relocs = 0; @@ -632,6 +663,10 @@ int main(int argc, char **argv) if (!fname) { usage(); } + + + regex_init(); + fp = fopen(fname, "r"); if (!fp) { die("Cannot open %s: %s\n", @@ -647,9 +682,10 @@ int main(int argc, char **argv) return 0; } if (show_absolute_relocs) { - print_absolute_relocs(); + print_absolute_relocs(stdout); return 0; } + err = print_absolute_relocs(stderr); emit_relocs(as_text); - return 0; + return err; } |