1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  13 Dec '05
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Linker no longer used - apart from mymalloc().
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Instead, simply compile and link switchback.c with test_xxx.c, e.g.:
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  ./> (cd .. && make EXTRA_CFLAGS="-m64" libvex_ppc64_linux.a) && gcc -m64 -Wall -O -g -o switchback switchback.c linker.c ../libvex_ppc64_linux.a test_bzip2.c
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h>
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h>
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <assert.h>
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <sys/types.h>
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <sys/stat.h>
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <unistd.h>
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <elf.h>
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <fcntl.h>
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <string.h>
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//#include <malloc.h>
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "linker.h"
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "../pub/libvex_basictypes.h"
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define IF_DEBUG(x,y) /* */
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int debug_linker = 0;
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(__x86_64__)
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#   define x86_64_TARGET_ARCH
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(__i386__)
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#   define i386_TARGET_ARCH
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined (__powerpc__)
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#   define ppc32_TARGET_ARCH
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#   error "Unknown arch"
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CALLOC_MAX 10000000
43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic HChar calloc_area[CALLOC_MAX];
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt calloc_used = 0;
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void* calloc_below2G ( Int n, Int m )
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* p;
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i;
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while ((calloc_used % 16) > 0) calloc_used++;
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(calloc_used + n*m < CALLOC_MAX);
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p = &calloc_area[calloc_used];
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < n*m; i++)
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     calloc_area[calloc_used+i] = 0;
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   calloc_used += n*m;
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return p;
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MYMALLOC_MAX 50*1000*1000
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic HChar mymalloc_area[MYMALLOC_MAX];
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt  mymalloc_used = 0;
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* mymalloc ( Int n )
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* p;
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(__powerpc64__)
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while ((ULong)(mymalloc_area+mymalloc_used) & 0xFFF)
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while ((UInt)(mymalloc_area+mymalloc_used) & 0xFFF)
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mymalloc_used++;
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(mymalloc_used+n < MYMALLOC_MAX);
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p = (void*)(&mymalloc_area[mymalloc_used]);
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mymalloc_used += n;
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //   printf("mymalloc(%d) = %p\n", n, p);
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return p;
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid myfree ( void* p )
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// TYPES
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define FALSE 0
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TRUE  1
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef enum { OBJECT_LOADED, OBJECT_RESOLVED } OStatus;
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define N_FIXUP_PAGES 1
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Indication of section kinds for loaded objects.  Needed by
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   the GC for deciding whether or not a pointer on the stack
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is a code pointer.
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   enum { SECTIONKIND_CODE_OR_RODATA,
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          SECTIONKIND_RWDATA,
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          SECTIONKIND_OTHER,
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          SECTIONKIND_NOINFOAVAIL }
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SectionKind;
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct _Section {
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      void* start;
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      void* end;
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      SectionKind kind;
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      struct _Section* next;
121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Section;
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct _ProddableBlock {
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      void* start;
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      int   size;
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      struct _ProddableBlock* next;
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ProddableBlock;
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Top-level structure for an object module.  One of these is allocated
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * for each object file in use.
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef struct _ObjectCode {
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    OStatus    status;
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char*      fileName;
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int        fileSize;
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char*      formatName;            /* eg "ELF32", "DLL", "COFF", etc. */
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* An array containing ptrs to all the symbol names copied from
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       this object into the global symbol hash table.  This is so that
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       we know which parts of the latter mapping to nuke when this
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       object is removed from the system. */
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char**     symbols;
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int        n_symbols;
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* ptr to malloc'd lump of memory holding the obj file */
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    void*      image;
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* Fixup area for long-distance jumps. */
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char*      fixup;
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int        fixup_used;
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int        fixup_size;
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* The section-kind entries for this object module.  Linked
157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       list. */
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    Section* sections;
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* A private hash table for local symbols. */
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* HashTable* */ void* lochash;
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* Allow a chain of these things */
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct _ObjectCode * next;
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* SANITY CHECK ONLY: a list of the only memory regions which may
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       safely be prodded during relocation.  Any attempt to prod
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       outside one of these is an error in the linker. */
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ProddableBlock* proddables;
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} ObjectCode;
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Define a set of types which can be used for both ELF32 and ELF64
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if VEX_HOST_WORDSIZE == 8
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELFCLASS    ELFCLASS64
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Addr    Elf64_Addr
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Word    Elf64_Word
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Sword   Elf64_Sword
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Ehdr    Elf64_Ehdr
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Phdr    Elf64_Phdr
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Shdr    Elf64_Shdr
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Sym     Elf64_Sym
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Rel     Elf64_Rel
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Rela    Elf64_Rela
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_ST_TYPE ELF64_ST_TYPE
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_ST_BIND ELF64_ST_BIND
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_R_TYPE  ELF64_R_TYPE
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_R_SYM   ELF64_R_SYM
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELFCLASS    ELFCLASS32
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Addr    Elf32_Addr
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Word    Elf32_Word
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Sword   Elf32_Sword
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Ehdr    Elf32_Ehdr
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Phdr    Elf32_Phdr
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Shdr    Elf32_Shdr
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Sym     Elf32_Sym
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Rel     Elf32_Rel
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define Elf_Rela    Elf32_Rela
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef ELF_ST_TYPE
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_ST_TYPE ELF32_ST_TYPE
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef ELF_ST_BIND
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_ST_BIND ELF32_ST_BIND
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef ELF_R_TYPE
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_R_TYPE  ELF32_R_TYPE
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef ELF_R_SYM
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define ELF_R_SYM   ELF32_R_SYM
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// PARANOIA
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -----------------------------------------------------------------------
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Sanity checking.  For each ObjectCode, maintain a list of address ranges
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * which may be prodded during relocation, and abort if we try and write
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * outside any of these.
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void addProddableBlock ( ObjectCode* oc, void* start, int size )
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ProddableBlock* pb
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      = mymalloc(sizeof(ProddableBlock));
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker)
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr, "aPB oc=%p %p %d   (%p .. %p)\n", oc, start, size,
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      start, ((char*)start)+size-1 );
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(size > 0);
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pb->start      = start;
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pb->size       = size;
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pb->next       = oc->proddables;
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->proddables = pb;
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void checkProddableBlock ( ObjectCode* oc, void* addr )
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ProddableBlock* pb;
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (pb = oc->proddables; pb != NULL; pb = pb->next) {
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      char* s = (char*)(pb->start);
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      char* e = s + pb->size - 1;
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      char* a = (char*)addr;
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Assumes that the biggest fixup involves a 4-byte write.  This
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         probably needs to be changed to 8 (ie, +7) on 64-bit
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         plats. */
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (a >= s && (a+3) <= e) return;
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fprintf(stderr,
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           "checkProddableBlock: invalid fixup %p in runtime linker\n",
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           addr);
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   exit(1);
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// String->Addr mappings
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct { char* mp_name; void* mp_addr; }
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Maplet;
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct {
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      int sm_size;
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      int sm_used;
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Maplet* maplets;
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   StringMap;
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic StringMap* new_StringMap ( void )
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   StringMap* sm = mymalloc(sizeof(StringMap));
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->sm_size = 10;
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->sm_used = 0;
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->maplets = mymalloc(10 * sizeof(Maplet));
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return sm;
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void delete_StringMap ( StringMap* sm )
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(sm->maplets != NULL);
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   myfree(sm->maplets);
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->maplets = NULL;
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   myfree(sm);
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void ensure_StringMap ( StringMap* sm )
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i;
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Maplet* mp2;
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(sm->maplets != NULL);
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sm->sm_used < sm->sm_size)
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     return;
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->sm_size *= 2;
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mp2 = mymalloc(sm->sm_size * sizeof(Maplet));
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < sm->sm_used; i++)
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mp2[i] = sm->maplets[i];
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   myfree(sm->maplets);
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->maplets = mp2;
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void* search_StringMap ( StringMap* sm, char* name )
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i;
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < sm->sm_used; i++)
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 == strcmp(name, sm->maplets[i].mp_name))
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return sm->maplets[i].mp_addr;
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return NULL;
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void addto_StringMap ( StringMap* sm, char* name, void* addr )
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ensure_StringMap(sm);
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->maplets[sm->sm_used].mp_name = name;
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->maplets[sm->sm_used].mp_addr = addr;
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sm->sm_used++;
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void paranoid_addto_StringMap ( StringMap* sm, char* name, void* addr )
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0)
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       fprintf(stderr, "paranoid_addto_StringMap(%s,%p)\n", name, addr);
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (search_StringMap(sm,name) != NULL) {
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr, "duplicate: paranoid_addto_StringMap(%s,%p)\n", name, addr);
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exit(1);
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   addto_StringMap(sm,name,addr);
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Top-level linker control.
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovStringMap*  global_symbol_table = NULL;
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovObjectCode* global_object_list = NULL;
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void initLinker ( void )
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (global_symbol_table != NULL)
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   global_symbol_table = new_StringMap();
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// SYMBOL TABLE(s)
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -----------------------------------------------------------------
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * lookup a symbol in the global symbol table
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid * lookupSymbol( char *lbl )
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void *val;
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   initLinker() ;
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(global_symbol_table != NULL);
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   val = search_StringMap(global_symbol_table, lbl);
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return val;
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// HELPERS
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Generic ELF functions
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic char *
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovfindElfSection ( void* objImage, Elf_Word sh_type )
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* ehdrC = (char*)objImage;
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Ehdr* ehdr = (Elf_Ehdr*)ehdrC;
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Shdr* shdr = (Elf_Shdr*)(ehdrC + ehdr->e_shoff);
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* ptr = NULL;
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i;
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < ehdr->e_shnum; i++) {
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[i].sh_type == sh_type
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          /* Ignore the section header's string table. */
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && i != ehdr->e_shstrndx
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  /* Ignore string tables named .stabstr, as they contain
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             debugging info. */
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && 0 != memcmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ) {
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ptr = ehdrC + shdr[i].sh_offset;
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ptr;
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef arm_TARGET_ARCH
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovchar* alloc_fixup_bytes ( ObjectCode* oc, int nbytes )
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* res;
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(nbytes % 4 == 0);
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(nbytes > 0);
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   res = &(oc->fixup[oc->fixup_used]);
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup_used += nbytes;
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (oc->fixup_used >= oc->fixup_size) {
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     fprintf(stderr, "fixup area too small for %s\n", oc->fileName);
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     exit(1);
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return res;
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// RESOLVE
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* lookup_magic_hacks ( char* sym )
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0==strcmp(sym, "printf")) return (void*)(&printf);
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return NULL;
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef arm_TARGET_ARCH
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid arm_notify_new_code ( char* start, int length )
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  __asm __volatile ("mov r1, %0\n\t"
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "mov r2, %1\n\t"
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "mov r3, %2\n\t"
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "swi 0x9f0002\n\t"
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    :
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    : "ir" (start), "ir" (length), "ir" (0) );
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid gen_armle_goto ( char* fixup, char* dstP )
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Elf_Word w = (Elf_Word)dstP;
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  /*
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   2                    .text
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   3 0000 04F01FE5              ldr     pc, value
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   4 0004 44332211      value:  .word   0x11223344
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fprintf(stderr,"at %p generating jump to %p\n", fixup, dstP );
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fixup[0] = 0x04; fixup[1] = 0xF0; fixup[2] = 0x1F; fixup[3] = 0xE5;
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fixup[4] = w & 0xFF; w >>= 8;
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fixup[5] = w & 0xFF; w >>= 8;
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fixup[6] = w & 0xFF; w >>= 8;
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  fixup[7] = w & 0xFF; w >>= 8;
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  arm_notify_new_code(fixup, 8);
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* arm_TARGET_ARCH */
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef ppc32_TARGET_ARCH
482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void invalidate_icache(void *ptr, int nbytes)
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unsigned long startaddr = (unsigned long) ptr;
485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unsigned long endaddr = startaddr + nbytes;
486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unsigned long addr;
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unsigned long cls = 16; //VG_(cache_line_size);
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   startaddr &= ~(cls - 1);
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (addr = startaddr; addr < endaddr; addr += cls)
491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      asm volatile("dcbst 0,%0" : : "r" (addr));
492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   asm volatile("sync");
493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (addr = startaddr; addr < endaddr; addr += cls)
494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      asm volatile("icbi 0,%0" : : "r" (addr));
495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   asm volatile("sync; isync");
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt compute_ppc_HA ( UInt x ) {
499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0xFFFF & ( (x >> 16) + ((x & 0x8000) ? 1 : 0) );
500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt compute_ppc_LO ( UInt x ) {
502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0xFFFF & x;
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt compute_ppc_HI ( UInt x ) {
505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0xFFFF & (x >> 16);
506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* ppc32_TARGET_ARCH */
508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Do ELF relocations which lack an explicit addend.  All x86-linux
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   relocations appear to be of this form. */
512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int
513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdo_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         Elf_Shdr* shdr, int shnum,
515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         Elf_Sym*  stab, char* strtab )
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int j;
518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char *symbol = NULL;
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Word* targ;
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Rel*  rtab = (Elf_Rel*) (ehdrC + shdr[shnum].sh_offset);
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int         nent = shdr[shnum].sh_size / sizeof(Elf_Rel);
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int target_shndx = shdr[shnum].sh_info;
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int symtab_shndx = shdr[shnum].sh_link;
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stab  = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   targ  = (Elf_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IF_DEBUG(linker,belch( "relocations for section %d using symtab %d",
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          target_shndx, symtab_shndx ));
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (j = 0; j < nent; j++) {
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr offset = rtab[j].r_offset;
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr info   = rtab[j].r_info;
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  P  = ((Elf_Addr)targ) + offset;
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Word* pP = (Elf_Word*)P;
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  A  = *pP;
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  S;
538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  value;
539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p)",
541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             j, (void*)offset, (void*)info ));
542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!info) {
543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IF_DEBUG(linker,belch( " ZERO" ));
544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         S = 0;
545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Elf_Sym sym = stab[ELF_R_SYM(info)];
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 /* First see if it is a local symbol. */
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ELF_ST_BIND(sym.st_info) == STB_LOCAL) {
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Yes, so we can get the address directly from the ELF symbol
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               table. */
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            symbol = sym.st_name==0 ? "(noname)" : strtab+sym.st_name;
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S = (Elf_Addr)
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                (ehdrC + shdr[ sym.st_shndx ].sh_offset
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       + stab[ELF_R_SYM(info)].st_value);
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 } else {
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* No, so look up the name in our global table. */
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            symbol = strtab + sym.st_name;
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S = (Elf_Addr)lookupSymbol( symbol );
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 }
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!S) {
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S = (Elf_Addr)lookup_magic_hacks(symbol);
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!S) {
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr,"%s: unknown symbol `%s'\n",
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           oc->fileName, symbol);
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    return 0;
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1)
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr, "\n`%s' resolves to %p\n", symbol, (void*)S );
571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1)
574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf(stderr, "Reloc: P = %p   S = %p   A = %p\n",
575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov			     (void*)P, (void*)S, (void*)A );
576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      checkProddableBlock ( oc, pP );
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      value = S + A;
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (ELF_R_TYPE(info)) {
581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        ifdef i386_TARGET_ARCH
582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_386_32:   *pP = value;     break;
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_386_PC32: *pP = value - P; break;
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        ifdef arm_TARGET_ARCH
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_ARM_PC24: {
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    Elf_Word w, delta, deltaTop8;
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* Generate a jump sequence into the fixup area
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	       and branch to that instead. */
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 	    char* fixup = alloc_fixup_bytes(oc, 8);
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* First of all, figure out where we're really trying to
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               jump to. */
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            // compensate for pc+8 bias
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Elf_Word real_dst = (A & 0x00FFFFFF) + 2;
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    // sign-extend 24-to-32 of real_dst
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (real_dst & 0x00800000)
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               real_dst |= 0xFF000000;
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               real_dst &= 0x00FFFFFF;
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            real_dst <<= 2;
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    real_dst += S;
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    gen_armle_goto(fixup, (char*)real_dst);
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* Delta is in bytes .. */
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            delta = (((Elf_Word)fixup) - ((Elf_Word)pP) - 8);
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            deltaTop8 = (delta >> 24) & 0xFF;
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (deltaTop8 != 0 && deltaTop8 != 0xFF) {
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      fprintf(stderr,"R_ARM_PC24: out of range delta 0x%x for %s\n",
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		      delta, symbol);
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      exit(1);
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    }
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            delta >>= 2;
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    w = *pP;
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w &= 0xFF000000;
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w |= (0x00FFFFFF & delta );
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *pP = w;
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_ARM_ABS32:
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    *pP = value;
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr,
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "%s: unhandled ELF relocation(Rel) type %d\n\n",
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		    oc->fileName, (Int)ELF_R_TYPE(info));
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return 0;
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Do ELF relocations for which explicit addends are supplied.
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sparc-solaris relocations appear to be of this form. */
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdo_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          Elf_Shdr* shdr, int shnum,
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          Elf_Sym*  stab, char* strtab )
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int j;
644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char *symbol;
645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Addr targ;
646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Rela* rtab = (Elf_Rela*) (ehdrC + shdr[shnum].sh_offset);
647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int         nent = shdr[shnum].sh_size / sizeof(Elf_Rela);
648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int target_shndx = shdr[shnum].sh_info;
649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int symtab_shndx = shdr[shnum].sh_link;
650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stab  = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   targ  = (Elf_Addr) (ehdrC + shdr[ target_shndx ].sh_offset);
653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IF_DEBUG(linker,belch( "relocations for section %d using symtab %d",
654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          target_shndx, symtab_shndx ));
655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (j = 0; j < nent; j++) {
657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(DEBUG) || defined(sparc_TARGET_ARCH)  \
658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   || defined(ia64_TARGET_ARCH)   \
659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   || defined(x86_64_TARGET_ARCH) \
660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   || defined(ppc32_TARGET_ARCH)
661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* This #ifdef only serves to avoid unused-var warnings. */
662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  offset = rtab[j].r_offset;
663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  P      = targ + offset;
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  info   = rtab[j].r_info;
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  A      = rtab[j].r_addend;
667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  S =0;
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr  value;
669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(sparc_TARGET_ARCH)
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Word* pP = (Elf_Word*)P;
671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Word  w1, w2;
672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     endif
673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(ia64_TARGET_ARCH)
674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf64_Xword *pP = (Elf64_Xword *)P;
675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Addr addr;
676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     endif
677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(x86_64_TARGET_ARCH)
678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ULong* pP = (ULong*)P;
679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     endif
680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(ppc32_TARGET_ARCH)
681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Int sI, sI2;
682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Word* pP = (Elf_Word*)P;
683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     endif
684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p %6p)   ",
686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             j, (void*)offset, (void*)info,
687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                (void*)A ));
688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!info) {
689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IF_DEBUG(linker,belch( " ZERO" ));
690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         S = 0;
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Elf_Sym sym = stab[ELF_R_SYM(info)];
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 /* First see if it is a local symbol. */
694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ELF_ST_BIND(sym.st_info) == STB_LOCAL) {
695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Yes, so we can get the address directly from the ELF symbol
696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               table. */
697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            symbol = sym.st_name==0 ? "(noname)" : strtab+sym.st_name;
698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S = (Elf_Addr)
699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                (ehdrC + shdr[ sym.st_shndx ].sh_offset
700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       + stab[ELF_R_SYM(info)].st_value);
701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef ELF_FUNCTION_DESC
702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* Make a function descriptor for this function */
703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (S && ELF_ST_TYPE(sym.st_info) == STT_FUNC) {
704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               S = allocateFunctionDesc(S + A);
705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       	       A = 0;
706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 } else {
709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* No, so look up the name in our global table. */
710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            symbol = strtab + sym.st_name;
711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S = (Elf_Addr)lookupSymbol( symbol );
712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef ELF_FUNCTION_DESC
714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* If a function, already a function descriptor - we would
715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	       have to copy it to add an offset. */
716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (S && (ELF_ST_TYPE(sym.st_info) == STT_FUNC) && (A != 0))
717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               belch("%s: function %s with addend %p", oc->fileName, symbol, (void *)A);
718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 }
720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!S) {
721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	   fprintf(stderr,"%s: unknown symbol `%s'\n", oc->fileName, symbol);
722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	   return 0;
723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (0)
725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr, "`%s' resolves to %p\n", symbol, (void*)S );
726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf ( stderr, "Reloc: offset = %p   P = %p   S = %p   A = %p\n",
730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           (void*)offset, (void*)P, (void*)S, (void*)A );
731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* checkProddableBlock ( oc, (void*)P ); */
734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      value = S + A;
736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (ELF_R_TYPE(info)) {
738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        if defined(sparc_TARGET_ARCH)
739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_SPARC_WDISP30:
740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 = *pP & 0xC0000000;
741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w2 = (Elf_Word)((value - P) >> 2);
742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ASSERT((w2 & 0xC0000000) == 0);
743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 |= w2;
744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *pP = w1;
745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_SPARC_HI22:
747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 = *pP & 0xFFC00000;
748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w2 = (Elf_Word)(value >> 10);
749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ASSERT((w2 & 0xFFC00000) == 0);
750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 |= w2;
751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *pP = w1;
752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_SPARC_LO10:
754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 = *pP & ~0x3FF;
755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w2 = (Elf_Word)(value & 0x3FF);
756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ASSERT((w2 & ~0x3FF) == 0);
757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w1 |= w2;
758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *pP = w1;
759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* According to the Sun documentation:
761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            R_SPARC_UA32
762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            This relocation type resembles R_SPARC_32, except it refers to an
763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            unaligned word. That is, the word to be relocated must be treated
764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            as four separate bytes with arbitrary alignment, not as a word
765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            aligned according to the architecture requirements.
766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (JRS: which means that freeloading on the R_SPARC_32 case
768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            is probably wrong, but hey ...)
769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_SPARC_UA32:
771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_SPARC_32:
772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w2 = (Elf_Word)value;
773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *pP = w2;
774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        if defined(ia64_TARGET_ARCH)
777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_DIR64LSB:
778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_FPTR64LSB:
779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    *pP = value;
780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_PCREL64LSB:
782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    *pP = value - P;
783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_SEGREL64LSB:
785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    addr = findElfSegment(ehdrC, value);
786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    *pP = value - addr;
787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_GPREL22:
789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    ia64_reloc_gprel22(P, value);
790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_LTOFF22:
792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_LTOFF22X:
793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_LTOFF_FPTR22:
794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    addr = allocateGOTEntry(value);
795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    ia64_reloc_gprel22(P, addr);
796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_PCREL21B:
798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    ia64_reloc_pcrel21(P, S, oc);
799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case R_IA64_LDXMOV:
801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* This goes with R_IA64_LTOFF22X and points to the load to
802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	       convert into a move.  We don't implement relaxation. */
803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    break;
804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        if defined(x86_64_TARGET_ARCH)
806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_X86_64_64: /* 1 *//* Direct 64 bit  */
807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((ULong*)pP) = (ULong)(S + A);
808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_X86_64_PC32: /* 2 *//* PC relative 32 bit signed */
810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) = (UInt)(S + A - P);
811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_X86_64_32: /* 10 *//* Direct 32 bit zero extended */
813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) = (UInt)(S + A);
814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_X86_64_32S: /* 11 *//* Direct 32 bit sign extended */
816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) = (UInt)(S + A);
817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        if defined(ppc32_TARGET_ARCH)
820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_PPC_ADDR32: /* 1 *//* 32bit absolute address */
821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) = S+A;
822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            invalidate_icache(pP,4);
823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_PPC_ADDR16_LO: /* 4 *//* lower 16bit of absolute address */
825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) &= 0x0000FFFF;
826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) |= 0xFFFF0000 & (compute_ppc_LO(S+A) << 16);
827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            invalidate_icache(pP,4);
828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_PPC_ADDR16_HA: /* 6 *//* adjusted high 16bit */
830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) &= 0x0000FFFF;
831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) |= 0xFFFF0000 & (compute_ppc_HA(S+A) << 16);
832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            invalidate_icache(pP,4);
833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_PPC_REL24: /* 10 *//* PC relative 26 bit */
835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            sI = S+A-P;
836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    sI >>= 2;
837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* the top 9 bits of sI must be the same (all 0s or
838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	       all 1s) for this to be valid; else we have to fail. */
839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            sI2 = sI >> 23; /* 23 == 32 - 9 */
840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (sI2 != 0 && sI2 != 0xFFFFFFFF) {
841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               fprintf(stderr, "%s: R_PPC_REL24 relocation failed\n", oc->fileName );
842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	       return 0;
843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) &= ~(0x00FFFFFF << 2);
845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) |= (0xFFFFFF & sI) << 2;
846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           invalidate_icache(pP,4);
847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case R_PPC_REL32: /* 26 */
849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *((UInt*)pP) = S+A-P;
850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            invalidate_icache(pP,4);
851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        endif
853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr,
855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "%s: unhandled ELF relocation(RelA) type %d\n",
856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		    oc->fileName, (Int)ELF_R_TYPE(info));
857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return 0;
858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int
866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovocResolve_ELF ( ObjectCode* oc )
867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char *strtab;
869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int   shnum, ok;
870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Sym*  stab  = NULL;
871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     ehdrC = (char*)(oc->image);
872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Ehdr* ehdr  = (Elf_Ehdr*) ehdrC;
873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Shdr* shdr  = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* first find "the" symbol table */
877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stab = (Elf_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* also go find the string table */
880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   strtab = findElfSection ( ehdrC, SHT_STRTAB );
881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (stab == NULL || strtab == NULL) {
883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: can't find string or symbol table\n", oc->fileName);
884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Process the relocation sections. */
888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (shnum = 0; shnum < ehdr->e_shnum; shnum++) {
889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Skip sections called ".rel.stab".  These appear to contain
891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         relocation entries that, when done, make the stabs debugging
892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         info point at the right places.  We ain't interested in all
893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         dat jazz, mun. */
894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 == memcmp(".rel.stab", sh_strtab + shdr[shnum].sh_name, 9))
895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         continue;
896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[shnum].sh_type == SHT_REL ) {
898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ok = do_Elf_Rel_relocations ( oc, ehdrC, shdr,
899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       shnum, stab, strtab );
900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!ok) return ok;
901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[shnum].sh_type == SHT_RELA) {
904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ok = do_Elf_Rela_relocations ( oc, ehdrC, shdr,
905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        shnum, stab, strtab );
906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!ok) return ok;
907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Free the local symbol table; we won't need it again. */
911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   delete_StringMap(oc->lochash);
912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->lochash = NULL;
913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// VERIFY
923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int
925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovocVerifyImage_ELF ( ObjectCode* oc )
926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Shdr* shdr;
928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Sym*  stab;
929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i, j, nent, nstrtab, nsymtabs;
930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* sh_strtab;
931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* strtab;
932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     ehdrC = (char*)(oc->image);
934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Ehdr* ehdr  = (Elf_Ehdr*)ehdrC;
935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       ehdr->e_ident[EI_MAG3] != ELFMAG3) {
940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: not an ELF object\n", oc->fileName);
941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_ident[EI_CLASS] != ELFCLASS) {
945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: unsupported ELF format\n", oc->fileName);
946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker)
951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf(stderr, "Is little-endian\n" );
952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else
953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       if (debug_linker)
955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          fprintf(stderr, "Is big-endian\n" );
956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       fprintf(stderr,"%s: unknown endiannness\n", oc->fileName);
958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       return 0;
959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_type != ET_REL) {
962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: not a relocatable object (.o) file\n", oc->fileName);
963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker)
966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr, "Is a relocatable object (.o) file\n" );
967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker)
969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr, "Architecture is " );
970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (ehdr->e_machine) {
971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_386:    if (debug_linker) fprintf(stderr, "x86\n" ); break;
972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_SPARC:  if (debug_linker) fprintf(stderr, "sparc\n" ); break;
973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_ARM:    if (debug_linker) fprintf(stderr, "arm\n" ); break;
974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef EM_IA_64
975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_IA_64:  if (debug_linker) fprintf(stderr, "ia64\n" ); break;
976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_X86_64: if (debug_linker) fprintf(stderr, "x86_64\n" ); break;
978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case EM_PPC:    if (debug_linker) fprintf(stderr, "ppc\n" ); break;
979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:        if (debug_linker) fprintf(stderr, "unknown\n" );
980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      fprintf(stderr,"%s: unknown architecture\n", oc->fileName);
981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      return 0;
982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker>1) fprintf(stderr,
985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             "\nSection header table: start %lld, n_entries %d, ent_size %d\n",
986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (Long)ehdr->e_shoff,
987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             ehdr->e_shnum, ehdr->e_shentsize  );
988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert (ehdr->e_shentsize == sizeof(Elf_Shdr));
990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   shdr = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ehdr->e_shstrndx == SHN_UNDEF) {
994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: no section header string table\n", oc->fileName);
995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1)
998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf(stderr, "Section header string table is section %d\n",
999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          ehdr->e_shstrndx);
1000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < ehdr->e_shnum; i++) {
1004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "%2d:  ", i );
1005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "type=%2d  ", (int)shdr[i].sh_type );
1006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "size=%4d  ", (int)shdr[i].sh_size );
1007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "offs=%4d  ", (int)shdr[i].sh_offset );
1008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "  (%p .. %p)  ",
1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ehdrC + shdr[i].sh_offset,
1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		      ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
1011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[i].sh_type == SHT_REL) {
1013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  if (debug_linker>1) fprintf(stderr, "Rel  " );
1014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else if (shdr[i].sh_type == SHT_RELA) {
1015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  if (debug_linker>1) fprintf(stderr, "RelA " );
1016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  if (debug_linker>1) fprintf(stderr,"     ");
1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (sh_strtab) {
1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  if (debug_linker>1) fprintf(stderr, "sname=%s\n",
1021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             sh_strtab + shdr[i].sh_name );
1022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker>1) fprintf(stderr, "\nString tables\n" );
1026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   strtab = NULL;
1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   nstrtab = 0;
1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < ehdr->e_shnum; i++) {
1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[i].sh_type == SHT_STRTAB
1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          /* Ignore the section header's string table. */
1031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && i != ehdr->e_shstrndx
1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	  /* Ignore string tables named .stabstr, as they contain
1033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             debugging info. */
1034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && 0 != memcmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ) {
1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1)
1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr,"   section %d is a normal string table\n", i );
1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         strtab = ehdrC + shdr[i].sh_offset;
1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         nstrtab++;
1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (nstrtab != 1) {
1043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: no string tables, or too many\n", oc->fileName);
1044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
1045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   nsymtabs = 0;
1048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (debug_linker>1) fprintf(stderr, "\nSymbol tables\n" );
1049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < ehdr->e_shnum; i++) {
1050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[i].sh_type != SHT_SYMTAB) continue;
1051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr, "section %d is a symbol table\n", i );
1052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nsymtabs++;
1053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stab = (Elf_Sym*) (ehdrC + shdr[i].sh_offset);
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nent = shdr[i].sh_size / sizeof(Elf_Sym);
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (debug_linker>1) fprintf(stderr,
1056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "   number of entries is apparently %d (%lld rem)\n",
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               nent,
1058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               (Long)(shdr[i].sh_size % sizeof(Elf_Sym))
1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             );
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 != shdr[i].sh_size % sizeof(Elf_Sym)) {
1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf(stderr,"%s: non-integral number of symbol table entries\n",
1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        oc->fileName);
1063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return 0;
1064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (j = 0; j < nent; j++) {
1066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "   %2d  ", j );
1067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "  sec=%-5d  size=%-3d  val=%5p  ",
1068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             (int)stab[j].st_shndx,
1069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             (int)stab[j].st_size,
1070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             (char*)stab[j].st_value );
1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "type=" );
1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (ELF_ST_TYPE(stab[j].st_info)) {
1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STT_NOTYPE:  if (debug_linker>1) fprintf(stderr, "notype " ); break;
1075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STT_OBJECT:  if (debug_linker>1) fprintf(stderr, "object " ); break;
1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STT_FUNC  :  if (debug_linker>1) fprintf(stderr, "func   " ); break;
1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STT_SECTION: if (debug_linker>1) fprintf(stderr, "section" ); break;
1078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STT_FILE:    if (debug_linker>1) fprintf(stderr, "file   " ); break;
1079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:          if (debug_linker>1) fprintf(stderr, "?      " ); break;
1080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "  " );
1082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "bind=" );
1084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (ELF_ST_BIND(stab[j].st_info)) {
1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STB_LOCAL :  if (debug_linker>1) fprintf(stderr, "local " ); break;
1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STB_GLOBAL:  if (debug_linker>1) fprintf(stderr, "global" ); break;
1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case STB_WEAK  :  if (debug_linker>1) fprintf(stderr, "weak  " ); break;
1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:          if (debug_linker>1) fprintf(stderr, "?     " ); break;
1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "  " );
1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (debug_linker>1) fprintf(stderr, "name=%s\n", strtab + stab[j].st_name );
1093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (nsymtabs == 0) {
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: didn't find any symbol tables\n", oc->fileName);
1098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
1099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
1102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
1109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// GETNAMES
1110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int
1112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovocGetNames_ELF ( ObjectCode* oc )
1113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int i, j, k, nent;
1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Sym* stab;
1116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     ehdrC     = (char*)(oc->image);
1118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Ehdr* ehdr      = (Elf_Ehdr*)ehdrC;
1119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     strtab    = findElfSection ( ehdrC, SHT_STRTAB );
1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Elf_Shdr* shdr      = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
1121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char*     sec_name;
1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(global_symbol_table != NULL);
1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!strtab) {
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"%s: no strtab\n", oc->fileName);
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   k = 0;
1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < ehdr->e_shnum; i++) {
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Figure out what kind of section it is.  Logic derived from
1135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Figure 1.14 ("Special Sections") of the ELF document
1136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ("Portable Formats Specification, Version 1.1"). */
1137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Elf_Shdr    hdr    = shdr[i];
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      SectionKind kind   = SECTIONKIND_OTHER;
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      int         is_bss = FALSE;
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (hdr.sh_type == SHT_PROGBITS
1142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_EXECINSTR)) {
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* .text-style section */
1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = SECTIONKIND_CODE_OR_RODATA;
1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
1147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (hdr.sh_type == SHT_PROGBITS
1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* .data-style section */
1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = SECTIONKIND_RWDATA;
1151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (hdr.sh_type == SHT_PROGBITS
1154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && (hdr.sh_flags & SHF_ALLOC) && !(hdr.sh_flags & SHF_WRITE)) {
1155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* .rodata-style section */
1156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = SECTIONKIND_CODE_OR_RODATA;
1157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (hdr.sh_type == SHT_NOBITS
1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* .bss-style section */
1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = SECTIONKIND_RWDATA;
1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         is_bss = TRUE;
1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_bss && shdr[i].sh_size > 0) {
1167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* This is a non-empty .bss section.  Allocate zeroed space for
1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            it, and set its .sh_offset field such that
1169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ehdrC + .sh_offset == addr_of_zeroed_space.  */
1170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         char* zspace = calloc(1, shdr[i].sh_size);
1171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         shdr[i].sh_offset = ((char*)zspace) - ((char*)ehdrC);
1172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 if (1)
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fprintf(stderr, "BSS section at %p, size %lld\n",
1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         zspace, (Long)shdr[i].sh_size);
1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* When loading objects compiled with -g, it seems there are
1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 relocations in various debug-info sections.  So we'd better
1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 tell addProddableBlock to allow those bits to be prodded. */
1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      //fprintf(stderr, "ZZZZZZZZZZ %s\n", sh_strtab + hdr.sh_name);
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      sec_name = sh_strtab + shdr[i].sh_name;
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (kind == SECTIONKIND_OTHER
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && (0 == strcmp(".debug_info", sec_name)
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              || 0 == strcmp(".debug_line", sec_name)
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              || 0 == strcmp(".debug_pubnames", sec_name)
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              || 0 == strcmp(".debug_aranges", sec_name)
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              || 0 == strcmp(".debug_frame", sec_name))) {
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = SECTIONKIND_CODE_OR_RODATA;
1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* fill in the section info */
1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (kind != SECTIONKIND_OTHER && shdr[i].sh_size > 0) {
1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addProddableBlock(oc, ehdrC + shdr[i].sh_offset, shdr[i].sh_size);
1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //addSection(oc, kind, ehdrC + shdr[i].sh_offset,
1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //               ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (shdr[i].sh_type != SHT_SYMTAB) continue;
1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* copy stuff into this module's object symbol table */
1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stab = (Elf_Sym*) (ehdrC + shdr[i].sh_offset);
1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nent = shdr[i].sh_size / sizeof(Elf_Sym);
1203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      oc->n_symbols = nent;
1205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      oc->symbols = mymalloc(oc->n_symbols * sizeof(char*));
1206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (j = 0; j < nent; j++) {
1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         char  isLocal = FALSE; /* avoids uninit-var warning */
1210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         char* ad      = NULL;
1211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         char* nm      = strtab + stab[j].st_name;
1212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         int   secno   = stab[j].st_shndx;
1213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 /* Figure out if we want to add it; if so, set ad to its
1215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            address.  Otherwise leave ad == NULL. */
1216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (secno == SHN_COMMON) {
1218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            isLocal = FALSE;
1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#           if defined(__x86_64__)
1220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ad = calloc_below2G(1, stab[j].st_size);
1221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#           else
1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ad = calloc(1, stab[j].st_size);
1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#           endif
1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //	    assert( Ptr_to_ULong(ad) < 0xF0000000ULL );
1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    if (0)
1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr, "COMMON symbol, size %lld name %s  allocd %p\n",
1228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            (Long)stab[j].st_size, nm, ad);
1229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* Pointless to do addProddableBlock() for this area,
1230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               since the linker should never poke around in it. */
1231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 }
1232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         else
1233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if ( ( ELF_ST_BIND(stab[j].st_info)==STB_GLOBAL
1234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                || ELF_ST_BIND(stab[j].st_info)==STB_LOCAL
1235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              )
1236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              /* and not an undefined symbol */
1237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              && stab[j].st_shndx != SHN_UNDEF
1238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      /* and not in a "special section" */
1239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              && stab[j].st_shndx < SHN_LORESERVE
1240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              &&
1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      /* and it's a not a section or string table or anything silly */
1242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              ( ELF_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                ELF_ST_TYPE(stab[j].st_info)==STT_OBJECT ||
1244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                ELF_ST_TYPE(stab[j].st_info)==STT_NOTYPE
1245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              )
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ) {
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /* Section 0 is the undefined section, hence > and not >=. */
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assert(secno > 0 && secno < ehdr->e_shnum);
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    /*
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (shdr[secno].sh_type == SHT_NOBITS) {
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               fprintf(stderr, "   BSS symbol, size %d off %d name %s\n",
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               stab[j].st_size, stab[j].st_value, nm);
1253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
1254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            */
1255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ad = ehdrC + shdr[ secno ].sh_offset + stab[j].st_value;
1256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (ELF_ST_BIND(stab[j].st_info)==STB_LOCAL) {
1257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               isLocal = TRUE;
1258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } else {
1259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef ELF_FUNCTION_DESC
1260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* dlsym() and the initialisation table both give us function
1261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		* descriptors, so to be consistent we store function descriptors
1262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		* in the symbol table */
1263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (ELF_ST_TYPE(stab[j].st_info) == STT_FUNC)
1264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   ad = (char *)allocateFunctionDesc((Elf_Addr)ad);
1265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (0|| debug_linker)
1267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   fprintf(stderr, "addOTabName(GLOB): %10p  %s %s\n",
1268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      ad, oc->fileName, nm );
1269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               isLocal = FALSE;
1270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
1271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* And the decision is ... */
1274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ad != NULL) {
1276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assert(nm != NULL);
1277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    oc->symbols[j] = nm;
1278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Acquire! */
1279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (isLocal) {
1280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Ignore entirely. */
1281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } else {
1282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      //ghciInsertStrHashTable(oc->fileName, global_symbol_table, nm, ad);
1283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	      paranoid_addto_StringMap(global_symbol_table, nm, ad);
1284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
1285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
1286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* Skip. */
1287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (debug_linker>1) fprintf(stderr, "skipping `%s'\n",
1288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   strtab + stab[j].st_name );
1289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /*
1290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fprintf(stderr,
1291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    "skipping   bind = %d,  type = %d,  shndx = %d   `%s'\n",
1292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    (int)ELF_ST_BIND(stab[j].st_info),
1293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    (int)ELF_ST_TYPE(stab[j].st_info),
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    (int)stab[j].st_shndx,
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    strtab + stab[j].st_name
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   );
1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            */
1298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            oc->symbols[j] = NULL;
1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
1305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov///////////////////////////////////////////////////////////////////
1311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
1312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// TOP-LEVEL CONTROL OF THE LINKER
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Load an obj (populate the global symbol table, but don't resolve yet)
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns: 1 if ok, 0 on error.
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint loadObj( char *path )
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ObjectCode* oc;
1324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct stat st;
1325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int r;
1326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int fd, pagesize;
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   char* p;
1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   initLinker();
1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fprintf(stderr, "==== loadObj %s ====\n", path );
1332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Check that we haven't already loaded this object.  */
1334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
1335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       ObjectCode *o;
1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       int is_dup = 0;
1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       for (o = global_object_list; o; o = o->next) {
1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          if (0 == strcmp(o->fileName, path))
1339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             is_dup = 1;
1340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       }
1341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       if (is_dup) {
1342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 fprintf(stderr,
1343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "\n\n"
1344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "GHCi runtime linker: warning: looks like you're trying to load the\n"
1345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "same object file twice:\n"
1346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "   %s\n"
1347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            , path);
1348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 exit(1);
1349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       }
1350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc = mymalloc(sizeof(ObjectCode));
1353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->formatName = "ELF";
1355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   r = stat(path, &st);
1357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (r == -1) { return 0; }
1358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* sigh, strdup() isn't a POSIX function, so do it the long way */
1360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fileName = mymalloc( strlen(path)+1 );
1361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   strcpy(oc->fileName, path);
1362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fileSize          = st.st_size;
1364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->symbols           = NULL;
1365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->sections          = NULL;
1366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->lochash           = new_StringMap();
1367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->proddables        = NULL;
1368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup             = NULL;
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup_used        = 0;
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup_size        = 0;
1371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* chain it onto the list of objects */
1373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->next              = global_object_list;
1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   global_object_list    = oc;
1375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fd = open(path, O_RDONLY);
1377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (fd == -1) {
1378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"loadObj: can't open `%s'\n", path);
1379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exit(1);
1380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Allocate a 1-page area just prior to the image, so we can put
1383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fixup code fragments there.  Used for doing R_ARM_PC24
1384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      relocations for jump distances > 64M. */
1385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pagesize = getpagesize();
1387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //   p = memalign(pagesize, N_FIXUP_PAGES * pagesize
1388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //                          + oc->fileSize);
1389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p = mymalloc(N_FIXUP_PAGES * pagesize + oc->fileSize);
1390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0) fprintf(stderr,"XXXX p = %p\n", p);
1391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (p == NULL) {
1392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"loadObj: failed to allocate space for `%s'\n", path);
1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exit(1);
1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup = p;
1397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup_size = N_FIXUP_PAGES * pagesize;
1398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->fixup_used = 0;
1399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->image = &(p[ oc->fixup_size ]);
1400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   r = read(fd, oc->image, oc->fileSize);
1402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (r != oc->fileSize) {
1403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fprintf(stderr,"loadObj: failed to read `%s'\n", path);
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exit(1);
1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fprintf(stderr, "loaded %s at %p (fixup = %p)\n",
1408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   oc->fileName, oc->image, oc->fixup );
1409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   close(fd);
1411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* verify the in-memory image */
1413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   r = ocVerifyImage_ELF ( oc );
1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!r) { return r; }
1415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* build the symbol list for this image */
1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   r = ocGetNames_ELF ( oc );
1418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!r) { return r; }
1419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* loaded, but not resolved yet */
1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   oc->status = OBJECT_LOADED;
1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef ppc32_TARGET_ARCH
1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   invalidate_icache(oc->image, oc->fileSize);
1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 1;
1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------------
1433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * resolve all the currently unlinked objects in memory
1434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns: 1 if ok, 0 on error.
1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint resolveObjs( void )
1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ObjectCode *oc;
1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int r;
1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    initLinker();
1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for (oc = global_object_list; oc; oc = oc->next) {
1446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	if (oc->status != OBJECT_RESOLVED) {
1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    r = ocResolve_ELF ( oc );
1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    if (!r) { return r; }
1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    oc->status = OBJECT_RESOLVED;
1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	}
1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return 1;
1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------------
1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Top-level linker.
1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Load and link a bunch of .o's, and return the address of
1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   'entry'.  Or NULL if something borks.
1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* linker_top_level_LINK ( int n_object_names, char** object_names )
1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int   r, i;
1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* mainp;
1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   initLinker();
1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < n_object_names; i++) {
1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      //fprintf(stderr, "linkloop %d %s\n", i, object_names[i] );
1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      r = loadObj( object_names[i] );
1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (r != 1) return NULL;
1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   r = resolveObjs();
1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (r != 1) return NULL;
1476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mainp = search_StringMap ( global_symbol_table, "entry" );
1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (mainp == NULL) return NULL;
1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf("switchback: Linker: success!\n");
1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return mainp;
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1484