Skip to content

Commit

Permalink
x86/vdso, build: Make LE access macros clearer, host-safe
Browse files Browse the repository at this point in the history
Make it a little clearer what the littleendian access macros in
vdso2c.[ch] actually do.  This way they can probably also be moved to
a central location (e.g. tools/include) for the benefit of other host
tools.

We should avoid implementation namespace symbols when writing code
that is compiling for the compiler host, so avoid names starting with
double underscore or underscore-capital.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/2cf258df123cb24bad63c274c8563c050547d99d.1401464755.git.luto@amacapital.net
  • Loading branch information
H. Peter Anvin committed May 31, 2014
1 parent add4eed commit c191920
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 39 deletions.
16 changes: 8 additions & 8 deletions arch/x86/vdso/vdso2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ static void fail(const char *format, ...)
/*
* Evil macros to do a little-endian read.
*/
#define __GET_TYPE(x, type, bits, ifnot) \
#define GLE(x, bits, ifnot) \
__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(x), type), \
le##bits##toh((x)), ifnot)
(sizeof(x) == bits/8), \
(__typeof__(x))le##bits##toh(x), ifnot)

extern void bad_get(uint64_t);
extern void bad_get_le(uint64_t);
#define LAST_LE(x) \
__builtin_choose_expr(sizeof(x) == 1, (x), bad_get_le(x))

#define GET(x) \
__GET_TYPE((x), __u32, 32, __GET_TYPE((x), __u64, 64, \
__GET_TYPE((x), __s32, 32, __GET_TYPE((x), __s64, 64, \
__GET_TYPE((x), __u16, 16, bad_get(x))))))
#define GET_LE(x) \
GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_LE(x))))

#define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))

Expand Down
65 changes: 34 additions & 31 deletions arch/x86/vdso/vdso2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,76 +18,79 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
const char *secstrings;
uint64_t syms[NSYMS] = {};

Elf_Phdr *pt = (Elf_Phdr *)(addr + GET(hdr->e_phoff));
Elf_Phdr *pt = (Elf_Phdr *)(addr + GET_LE(hdr->e_phoff));

/* Walk the segment table. */
for (i = 0; i < GET(hdr->e_phnum); i++) {
if (GET(pt[i].p_type) == PT_LOAD) {
for (i = 0; i < GET_LE(hdr->e_phnum); i++) {
if (GET_LE(pt[i].p_type) == PT_LOAD) {
if (found_load)
fail("multiple PT_LOAD segs\n");

if (GET(pt[i].p_offset) != 0 ||
GET(pt[i].p_vaddr) != 0)
if (GET_LE(pt[i].p_offset) != 0 ||
GET_LE(pt[i].p_vaddr) != 0)
fail("PT_LOAD in wrong place\n");

if (GET(pt[i].p_memsz) != GET(pt[i].p_filesz))
if (GET_LE(pt[i].p_memsz) != GET_LE(pt[i].p_filesz))
fail("cannot handle memsz != filesz\n");

load_size = GET(pt[i].p_memsz);
load_size = GET_LE(pt[i].p_memsz);
found_load = 1;
} else if (GET(pt[i].p_type) == PT_DYNAMIC) {
dyn = addr + GET(pt[i].p_offset);
dyn_end = addr + GET(pt[i].p_offset) +
GET(pt[i].p_memsz);
} else if (GET_LE(pt[i].p_type) == PT_DYNAMIC) {
dyn = addr + GET_LE(pt[i].p_offset);
dyn_end = addr + GET_LE(pt[i].p_offset) +
GET_LE(pt[i].p_memsz);
}
}
if (!found_load)
fail("no PT_LOAD seg\n");
data_size = (load_size + 4095) / 4096 * 4096;

/* Walk the dynamic table */
for (i = 0; dyn + i < dyn_end && GET(dyn[i].d_tag) != DT_NULL; i++) {
typeof(dyn[i].d_tag) tag = GET(dyn[i].d_tag);
for (i = 0; dyn + i < dyn_end &&
GET_LE(dyn[i].d_tag) != DT_NULL; i++) {
typeof(dyn[i].d_tag) tag = GET_LE(dyn[i].d_tag);
if (tag == DT_REL || tag == DT_RELSZ ||
tag == DT_RELENT || tag == DT_TEXTREL)
fail("vdso image contains dynamic relocations\n");
}

/* Walk the section table */
secstrings_hdr = addr + GET(hdr->e_shoff) +
GET(hdr->e_shentsize)*GET(hdr->e_shstrndx);
secstrings = addr + GET(secstrings_hdr->sh_offset);
for (i = 0; i < GET(hdr->e_shnum); i++) {
Elf_Shdr *sh = addr + GET(hdr->e_shoff) +
GET(hdr->e_shentsize) * i;
if (GET(sh->sh_type) == SHT_SYMTAB)
secstrings_hdr = addr + GET_LE(hdr->e_shoff) +
GET_LE(hdr->e_shentsize)*GET_LE(hdr->e_shstrndx);
secstrings = addr + GET_LE(secstrings_hdr->sh_offset);
for (i = 0; i < GET_LE(hdr->e_shnum); i++) {
Elf_Shdr *sh = addr + GET_LE(hdr->e_shoff) +
GET_LE(hdr->e_shentsize) * i;
if (GET_LE(sh->sh_type) == SHT_SYMTAB)
symtab_hdr = sh;

if (!strcmp(secstrings + GET(sh->sh_name), ".altinstructions"))
if (!strcmp(secstrings + GET_LE(sh->sh_name),
".altinstructions"))
alt_sec = sh;
}

if (!symtab_hdr)
fail("no symbol table\n");

strtab_hdr = addr + GET(hdr->e_shoff) +
GET(hdr->e_shentsize) * GET(symtab_hdr->sh_link);
strtab_hdr = addr + GET_LE(hdr->e_shoff) +
GET_LE(hdr->e_shentsize) * GET_LE(symtab_hdr->sh_link);

/* Walk the symbol table */
for (i = 0; i < GET(symtab_hdr->sh_size) / GET(symtab_hdr->sh_entsize);
for (i = 0;
i < GET_LE(symtab_hdr->sh_size) / GET_LE(symtab_hdr->sh_entsize);
i++) {
int k;
Elf_Sym *sym = addr + GET(symtab_hdr->sh_offset) +
GET(symtab_hdr->sh_entsize) * i;
const char *name = addr + GET(strtab_hdr->sh_offset) +
GET(sym->st_name);
Elf_Sym *sym = addr + GET_LE(symtab_hdr->sh_offset) +
GET_LE(symtab_hdr->sh_entsize) * i;
const char *name = addr + GET_LE(strtab_hdr->sh_offset) +
GET_LE(sym->st_name);
for (k = 0; k < NSYMS; k++) {
if (!strcmp(name, required_syms[k])) {
if (syms[k]) {
fail("duplicate symbol %s\n",
required_syms[k]);
}
syms[k] = GET(sym->st_value);
syms[k] = GET_LE(sym->st_value);
}
}
}
Expand Down Expand Up @@ -147,9 +150,9 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name)
fprintf(outfile, "\t},\n");
if (alt_sec) {
fprintf(outfile, "\t.alt = %lu,\n",
(unsigned long)GET(alt_sec->sh_offset));
(unsigned long)GET_LE(alt_sec->sh_offset));
fprintf(outfile, "\t.alt_len = %lu,\n",
(unsigned long)GET(alt_sec->sh_size));
(unsigned long)GET_LE(alt_sec->sh_size));
}
for (i = 0; i < NSYMS; i++) {
if (syms[i])
Expand Down

0 comments on commit c191920

Please sign in to comment.