on linux/nommu, non-writable private mappings of files may actually use memory shared with other processes or the fs cache. the old nommu loader code (used when mmap with MAP_FIXED fails) simply wrote over top of the original file mapping, possibly clobbering this shared memory. no such breakage was observed in practice, but it should have been possible. the new code starts by mapping anonymous writable memory on archs that might support nommu, then maps load segments over top of it, falling back to read if MAP_FIXED fails. we use an anonymous map rather than a writable file map to avoid reading more data from disk than needed. since pages cannot be loaded lazily on fault, in case of large data/bss, mapping the full file may read a lot of data that will subsequently be thrown away when processing additional LOAD segments. as a result, we cannot skip the first LOAD segment when operating in this mode. these changes affect only non-FDPIC nommu support.
93 lines
1.7 KiB
C
93 lines
1.7 KiB
C
#ifndef _INTERNAL_RELOC_H
|
|
#define _INTERNAL_RELOC_H
|
|
|
|
#include <features.h>
|
|
#include <elf.h>
|
|
#include <stdint.h>
|
|
|
|
#if UINTPTR_MAX == 0xffffffff
|
|
typedef Elf32_Ehdr Ehdr;
|
|
typedef Elf32_Phdr Phdr;
|
|
typedef Elf32_Sym Sym;
|
|
#define R_TYPE(x) ((x)&255)
|
|
#define R_SYM(x) ((x)>>8)
|
|
#else
|
|
typedef Elf64_Ehdr Ehdr;
|
|
typedef Elf64_Phdr Phdr;
|
|
typedef Elf64_Sym Sym;
|
|
#define R_TYPE(x) ((x)&0x7fffffff)
|
|
#define R_SYM(x) ((x)>>32)
|
|
#endif
|
|
|
|
/* These enum constants provide unmatchable default values for
|
|
* any relocation type the arch does not use. */
|
|
enum {
|
|
REL_NONE = 0,
|
|
REL_SYMBOLIC = -100,
|
|
REL_GOT,
|
|
REL_PLT,
|
|
REL_RELATIVE,
|
|
REL_OFFSET,
|
|
REL_OFFSET32,
|
|
REL_COPY,
|
|
REL_SYM_OR_REL,
|
|
REL_DTPMOD,
|
|
REL_DTPOFF,
|
|
REL_TPOFF,
|
|
REL_TPOFF_NEG,
|
|
REL_TLSDESC,
|
|
REL_FUNCDESC,
|
|
REL_FUNCDESC_VAL,
|
|
};
|
|
|
|
struct fdpic_loadseg {
|
|
uintptr_t addr, p_vaddr, p_memsz;
|
|
};
|
|
|
|
struct fdpic_loadmap {
|
|
unsigned short version, nsegs;
|
|
struct fdpic_loadseg segs[];
|
|
};
|
|
|
|
struct fdpic_dummy_loadmap {
|
|
unsigned short version, nsegs;
|
|
struct fdpic_loadseg segs[1];
|
|
};
|
|
|
|
#include "reloc.h"
|
|
|
|
#ifndef FDPIC_CONSTDISP_FLAG
|
|
#define FDPIC_CONSTDISP_FLAG 0
|
|
#endif
|
|
|
|
#ifndef DL_FDPIC
|
|
#define DL_FDPIC 0
|
|
#endif
|
|
|
|
#ifndef DL_NOMMU_SUPPORT
|
|
#define DL_NOMMU_SUPPORT 0
|
|
#endif
|
|
|
|
#if !DL_FDPIC
|
|
#define IS_RELATIVE(x,s) ( \
|
|
(R_TYPE(x) == REL_RELATIVE) || \
|
|
(R_TYPE(x) == REL_SYM_OR_REL && !R_SYM(x)) )
|
|
#else
|
|
#define IS_RELATIVE(x,s) ( ( \
|
|
(R_TYPE(x) == REL_FUNCDESC_VAL) || \
|
|
(R_TYPE(x) == REL_SYMBOLIC) ) \
|
|
&& (((s)[R_SYM(x)].st_info & 0xf) == STT_SECTION) )
|
|
#endif
|
|
|
|
#ifndef NEED_MIPS_GOT_RELOCS
|
|
#define NEED_MIPS_GOT_RELOCS 0
|
|
#endif
|
|
|
|
#define AUX_CNT 32
|
|
#define DYN_CNT 32
|
|
|
|
typedef void (*stage2_func)(unsigned char *, size_t *);
|
|
typedef _Noreturn void (*stage3_func)(size_t *);
|
|
|
|
#endif
|