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