2 * Copyright (C) 2015 Imagination Technologies
3 * Author: Alex Smith <alex.smith@imgtec.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
11 static inline bool FUNC(patch_vdso
)(const char *path
, void *vdso
)
13 const ELF(Ehdr
) *ehdr
= vdso
;
16 char *shstrtab
, *name
;
17 uint16_t sh_count
, sh_entsize
, i
;
18 unsigned int local_gotno
, symtabno
, gotsym
;
21 shdrs
= vdso
+ FUNC(swap_uint
)(ehdr
->e_shoff
);
22 sh_count
= swap_uint16(ehdr
->e_shnum
);
23 sh_entsize
= swap_uint16(ehdr
->e_shentsize
);
25 shdr
= shdrs
+ (sh_entsize
* swap_uint16(ehdr
->e_shstrndx
));
26 shstrtab
= vdso
+ FUNC(swap_uint
)(shdr
->sh_offset
);
28 for (i
= 0; i
< sh_count
; i
++) {
29 shdr
= shdrs
+ (i
* sh_entsize
);
30 name
= shstrtab
+ swap_uint32(shdr
->sh_name
);
33 * Ensure there are no relocation sections - ld.so does not
34 * relocate the VDSO so if there are relocations things will
37 switch (swap_uint32(shdr
->sh_type
)) {
41 "%s: '%s' contains relocation sections\n",
45 dyn
= vdso
+ FUNC(swap_uint
)(shdr
->sh_offset
);
49 /* Check for existing sections. */
50 if (strcmp(name
, ".MIPS.abiflags") == 0) {
52 "%s: '%s' already contains a '.MIPS.abiflags' section\n",
57 if (strcmp(name
, ".mips_abiflags") == 0) {
58 strcpy(name
, ".MIPS.abiflags");
59 shdr
->sh_type
= swap_uint32(SHT_MIPS_ABIFLAGS
);
60 shdr
->sh_entsize
= shdr
->sh_size
;
65 * Ensure the GOT has no entries other than the standard 2, for the same
66 * reason we check that there's no relocation sections above.
67 * The standard two entries are:
72 local_gotno
= symtabno
= gotsym
= 0;
74 while (FUNC(swap_uint
)(dyn
->d_tag
) != DT_NULL
) {
75 switch (FUNC(swap_uint
)(dyn
->d_tag
)) {
77 * This member holds the number of local GOT entries.
79 case DT_MIPS_LOCAL_GOTNO
:
80 local_gotno
= FUNC(swap_uint
)(dyn
->d_un
.d_val
);
83 * This member holds the number of entries in the
86 case DT_MIPS_SYMTABNO
:
87 symtabno
= FUNC(swap_uint
)(dyn
->d_un
.d_val
);
90 * This member holds the index of the first dynamic
91 * symbol table entry that corresponds to an entry in
95 gotsym
= FUNC(swap_uint
)(dyn
->d_un
.d_val
);
102 if (local_gotno
> 2 || symtabno
- gotsym
) {
104 "%s: '%s' contains unexpected GOT entries\n",
113 static inline bool FUNC(get_symbols
)(const char *path
, void *vdso
)
115 const ELF(Ehdr
) *ehdr
= vdso
;
116 void *shdrs
, *symtab
;
120 uint16_t sh_count
, sh_entsize
, st_count
, st_entsize
, i
, j
;
124 shdrs
= vdso
+ FUNC(swap_uint
)(ehdr
->e_shoff
);
125 sh_count
= swap_uint16(ehdr
->e_shnum
);
126 sh_entsize
= swap_uint16(ehdr
->e_shentsize
);
128 for (i
= 0; i
< sh_count
; i
++) {
129 shdr
= shdrs
+ (i
* sh_entsize
);
131 if (swap_uint32(shdr
->sh_type
) == SHT_SYMTAB
)
136 fprintf(stderr
, "%s: '%s' has no symbol table\n", program_name
,
142 flags
= swap_uint32(ehdr
->e_flags
);
143 if (elf_class
== ELFCLASS64
)
145 else if (flags
& EF_MIPS_ABI2
)
150 /* Get symbol table. */
151 symtab
= vdso
+ FUNC(swap_uint
)(shdr
->sh_offset
);
152 st_entsize
= FUNC(swap_uint
)(shdr
->sh_entsize
);
153 st_count
= FUNC(swap_uint
)(shdr
->sh_size
) / st_entsize
;
155 /* Get string table. */
156 shdr
= shdrs
+ (swap_uint32(shdr
->sh_link
) * sh_entsize
);
157 strtab
= vdso
+ FUNC(swap_uint
)(shdr
->sh_offset
);
159 /* Write offsets for symbols needed by the kernel. */
160 for (i
= 0; vdso_symbols
[i
].name
; i
++) {
161 if (!(vdso_symbols
[i
].abis
& elf_abi
))
164 for (j
= 0; j
< st_count
; j
++) {
165 sym
= symtab
+ (j
* st_entsize
);
166 name
= strtab
+ swap_uint32(sym
->st_name
);
168 if (!strcmp(name
, vdso_symbols
[i
].name
)) {
169 offset
= FUNC(swap_uint
)(sym
->st_value
);
172 "\t.%s = 0x%" PRIx64
",\n",
173 vdso_symbols
[i
].offset_name
, offset
);
180 "%s: '%s' is missing required symbol '%s'\n",
181 program_name
, path
, vdso_symbols
[i
].name
);