Fix regular expression at doc/rdsrc.pl
[platform/upstream/nasm.git] / rdoff / rdfload.c
1 /* ----------------------------------------------------------------------- *
2  *   
3  *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *     
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33
34 /*
35  * rdfload.c    RDOFF Object File loader library
36  */
37
38 /*
39  * TODO: this has been modified from previous version only in very
40  * simplistic ways. Needs to be improved drastically, especially:
41  *   - support for more than the 2 standard segments
42  *   - support for segment relocations (hard to do in ANSI C)
43  */
44
45 #include "compiler.h"
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 #include "rdfload.h"
52 #include "symtab.h"
53 #include "collectn.h"
54
55 extern int rdf_errno;
56
57 rdfmodule *rdfload(const char *filename)
58 {
59     rdfmodule *f;
60     int32_t bsslength = 0;
61     char *hdr;
62     rdfheaderrec *r;
63
64     f = malloc(sizeof(rdfmodule));
65     if (f == NULL) {
66         rdf_errno = RDF_ERR_NOMEM;
67         return NULL;
68     }
69
70     f->symtab = symtabNew();
71     if (!f->symtab) {
72         free(f);
73         rdf_errno = RDF_ERR_NOMEM;
74         return NULL;
75     }
76
77     /* open the file */
78     if (rdfopen(&(f->f), filename)) {
79         free(f);
80         return NULL;
81     }
82
83     /* read in text and data segments, and header */
84
85     f->t = malloc(f->f.seg[0].length);
86     f->d = malloc(f->f.seg[1].length);  /* BSS seg allocated later */
87     hdr = malloc(f->f.header_len);
88
89     if (!f->t || !f->d || !hdr) {
90         rdf_errno = RDF_ERR_NOMEM;
91         rdfclose(&f->f);
92         if (f->t)
93             free(f->t);
94         if (f->d)
95             free(f->d);
96         free(f);
97         free(hdr);
98         return NULL;
99     }
100
101     if (rdfloadseg(&f->f, RDOFF_HEADER, hdr) ||
102         rdfloadseg(&f->f, RDOFF_CODE, f->t) ||
103         rdfloadseg(&f->f, RDOFF_DATA, f->d)) {
104         rdfclose(&f->f);
105         free(f->t);
106         free(f->d);
107         free(f);
108         free(hdr);
109         return NULL;
110     }
111
112     rdfclose(&f->f);
113
114     /* Allocate BSS segment; step through header and count BSS records */
115
116     while ((r = rdfgetheaderrec(&f->f))) {
117         if (r->type == 5)
118             bsslength += r->b.amount;
119     }
120
121     f->b = malloc(bsslength);
122     if (bsslength && (!f->b)) {
123         free(f->t);
124         free(f->d);
125         free(f);
126         free(hdr);
127         rdf_errno = RDF_ERR_NOMEM;
128         return NULL;
129     }
130
131     rdfheaderrewind(&f->f);
132
133     f->textrel = (int32_t)(size_t)f->t;
134     f->datarel = (int32_t)(size_t)f->d;
135     f->bssrel  = (int32_t)(size_t)f->b;
136
137     return f;
138 }
139
140 int rdf_relocate(rdfmodule * m)
141 {
142     rdfheaderrec *r;
143     Collection imports;
144     symtabEnt e;
145     int32_t rel;
146     uint8_t *seg;
147
148     rdfheaderrewind(&m->f);
149     collection_init(&imports);
150
151     while ((r = rdfgetheaderrec(&m->f))) {
152         switch (r->type) {
153         case 1:                /* Relocation record */
154
155             /* calculate relocation factor */
156
157             if (r->r.refseg == 0)
158                 rel = m->textrel;
159             else if (r->r.refseg == 1)
160                 rel = m->datarel;
161             else if (r->r.refseg == 2)
162                 rel = m->bssrel;
163             else
164                 /* We currently do not support load-time linkage.
165                    This should be added some time soon... */
166
167                 return 1;       /* return error code */
168
169             if ((r->r.segment & 63) == 0)
170                 seg = m->t;
171             else if ((r->r.segment & 63) == 1)
172                 seg = m->d;
173             else
174                 continue;       /* relocation not in a loaded segment */
175
176             /* it doesn't matter in this case that the code is non-portable,
177                as the entire concept of executing a module like this is
178                non-portable */
179             switch (r->r.length) {
180             case 1:
181                 seg[r->r.offset] += (char)rel;
182                 break;
183             case 2:
184                 *(uint16_t *) (seg + r->r.offset) += (uint16_t) rel;
185                 break;
186             case 4:
187                 *(int32_t *)(seg + r->r.offset) += rel;
188                 break;
189             }
190             break;
191
192         case 3:                /* export record - add to symtab */
193             e.segment = r->e.segment;
194             e.offset = r->e.offset + (e.segment == 0 ? m->textrel :     /* 0 -> code */
195                                       e.segment == 1 ? m->datarel :     /* 1 -> data */
196                                       m->bssrel);       /* 2 -> bss  */
197             e.flags = 0;
198             e.name = malloc(strlen(r->e.label) + 1);
199             if (!e.name)
200                 return 1;
201
202             strcpy(e.name, r->e.label);
203             symtabInsert(m->symtab, &e);
204             break;
205
206         case 6:                /* segment relocation */
207             fprintf(stderr, "%s: segment relocation not supported by this "
208                     "loader\n", m->f.name);
209             return 1;
210         }
211     }
212     return 0;
213 }