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