|
1 /* |
|
2 * Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <stdlib.h> |
|
20 #include <string.h> |
|
21 #include <e32std.h> |
|
22 #include "elftran.h" |
|
23 #include "elffile.h" |
|
24 #include "h_utl.h" |
|
25 #include <assert.h> |
|
26 |
|
27 TInt sizeOfRelocs(Elf32_Rel **relocs, TInt nrelocs) |
|
28 { |
|
29 |
|
30 TInt bytecount=0; |
|
31 TInt page=-1; |
|
32 TInt i; |
|
33 for (i=0; i<nrelocs; i++) |
|
34 { |
|
35 TInt p=relocs[i]->r_offset&0xfffff000; |
|
36 if (page!=p) |
|
37 { |
|
38 if (bytecount%4!=0) |
|
39 bytecount+=2; |
|
40 bytecount+=8; // page, block size |
|
41 page=p; |
|
42 } |
|
43 bytecount+=2; |
|
44 } |
|
45 if (bytecount%4!=0) |
|
46 bytecount+=2; |
|
47 return bytecount; |
|
48 } |
|
49 |
|
50 char* E32ImageFile_ELF::CreateRelocs(ELFFile& aElfFile, Elf32_Rel **relocs, TInt nrelocs, TInt &aSize, TUint aBase) |
|
51 { |
|
52 |
|
53 TInt bytecount=sizeOfRelocs(relocs, nrelocs); |
|
54 aSize=0; |
|
55 if (bytecount==0) |
|
56 return NULL; |
|
57 aSize=bytecount+sizeof(E32RelocSection); |
|
58 |
|
59 char *section=new char [bytecount+sizeof(E32RelocSection)]; |
|
60 char *data=section+sizeof(E32RelocSection); |
|
61 char *startofblock=data; |
|
62 |
|
63 TInt page=-1; |
|
64 TInt pagesize=8; |
|
65 TInt i; |
|
66 for (i=0; i<nrelocs; i++) |
|
67 { |
|
68 TInt p=relocs[i]->r_offset&0xfffff000; |
|
69 if (page!=p) |
|
70 { |
|
71 if (pagesize%4!=0) |
|
72 { |
|
73 *(TUint16 *)data=0; |
|
74 data+=2; |
|
75 pagesize+=2; |
|
76 } |
|
77 if (page == -1) page = p; |
|
78 *(TUint *)startofblock=page - aBase; |
|
79 *(TUint *)(startofblock+4)=pagesize; |
|
80 pagesize=8; |
|
81 page=p; |
|
82 startofblock=data; |
|
83 data+=8; |
|
84 } |
|
85 TUint16 relocType = aElfFile.GetRelocType(relocs[i]); |
|
86 *(TUint16 *)data=(TUint16)((relocs[i]->r_offset&0xfff)|relocType); |
|
87 data+=2; |
|
88 pagesize+=2; |
|
89 } |
|
90 if (pagesize%4!=0) |
|
91 { |
|
92 *(TUint16 *)data=0; |
|
93 data+=2; |
|
94 pagesize+=2; |
|
95 } |
|
96 *(TUint *)startofblock=page - aBase; |
|
97 *(TUint *)(startofblock+4)=pagesize; |
|
98 ((E32RelocSection *)section)->iNumberOfRelocs=nrelocs; |
|
99 ((E32RelocSection *)section)->iSize=bytecount; |
|
100 return section; |
|
101 } |
|
102 |
|
103 void checkreloc(ELFFile& aElfFile, TUint va, TUint reloc) |
|
104 { |
|
105 // This will warn if appears to be outside any known segment. |
|
106 // NB. Such relocations can occur as the result of 'optimizations' |
|
107 // and aren't 'bugs'. |
|
108 // It turns out that the released version of RVCT makes such widespread |
|
109 // use of the optimization that this warning is disconcerting and |
|
110 // unhelpful. |
|
111 (void) aElfFile; |
|
112 (void)va; |
|
113 (void)reloc; |
|
114 #if 0 |
|
115 if (!aElfFile.GetSegmentFromAddr(va)) |
|
116 Print(EWarning, "dubious relocation: [%08x] = %08x\n", reloc, va); |
|
117 #endif |
|
118 } |
|
119 |
|
120 void E32ImageFile_ELF::FixRelocs(ELFFile &aElfFile, Elf32_Rel **codeRelocs, Elf32_Rel **dataRelocs) |
|
121 { |
|
122 TUint *data; |
|
123 TInt numberOfCodeRelocs = aElfFile.NumberOfCodeRelocs(); |
|
124 TInt numberOfDataRelocs = aElfFile.NumberOfDataRelocs(); |
|
125 for (TInt i=0; i<numberOfCodeRelocs; i++) |
|
126 { |
|
127 data=aElfFile.CodePtrFromAddr(codeRelocs[i]->r_offset); |
|
128 checkreloc(aElfFile, *data, codeRelocs[i]->r_offset); |
|
129 //*data=FixAddress(aElfFile, *data, codeRelocs[i]); |
|
130 } |
|
131 // fix defect |
|
132 for (TInt j=0; j<numberOfDataRelocs; j++) |
|
133 { |
|
134 data=aElfFile.DataPtrFromAddr(dataRelocs[j]->r_offset); |
|
135 checkreloc(aElfFile, *data, dataRelocs[j]->r_offset); |
|
136 //*data=FixAddress(aElfFile, *data, dataRelocs[j]); |
|
137 } |
|
138 } |
|
139 |
|
140 TUint E32ImageFile_ELF::FixAddress(ELFFile &aElfFile, TUint va, Elf32_Rel * rel) |
|
141 // |
|
142 // Fix the given virtual address for the new headers |
|
143 // |
|
144 { |
|
145 Elf32_Phdr * segment = aElfFile.GetSegmentFromAddr(rel->r_offset); |
|
146 assert(aElfFile.CodeSegmentP(segment) || aElfFile.DataSegmentP(segment)); |
|
147 TUint offset = va - segment->p_vaddr; |
|
148 if (aElfFile.CodeSegmentP(segment)) |
|
149 return (TUint)aElfFile.GetCode() + offset; |
|
150 else |
|
151 return (TUint)aElfFile.GetData() + offset; |
|
152 |
|
153 } |
|
154 |