simple-object.c revision 1.1.1.7 1 1.1 christos /* simple-object.c -- simple routines to read and write object files.
2 1.1.1.7 christos Copyright (C) 2010-2022 Free Software Foundation, Inc.
3 1.1 christos Written by Ian Lance Taylor, Google.
4 1.1 christos
5 1.1 christos This program is free software; you can redistribute it and/or modify it
6 1.1 christos under the terms of the GNU General Public License as published by the
7 1.1 christos Free Software Foundation; either version 2, or (at your option) any
8 1.1 christos later version.
9 1.1 christos
10 1.1 christos This program is distributed in the hope that it will be useful,
11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 1.1 christos GNU General Public License for more details.
14 1.1 christos
15 1.1 christos You should have received a copy of the GNU General Public License
16 1.1 christos along with this program; if not, write to the Free Software
17 1.1 christos Foundation, 51 Franklin Street - Fifth Floor,
18 1.1 christos Boston, MA 02110-1301, USA. */
19 1.1 christos
20 1.1 christos #include "config.h"
21 1.1 christos #include "libiberty.h"
22 1.1 christos #include "simple-object.h"
23 1.1 christos
24 1.1 christos #include <errno.h>
25 1.1.1.4 christos #include <fcntl.h>
26 1.1 christos
27 1.1 christos #ifdef HAVE_STDLIB_H
28 1.1 christos #include <stdlib.h>
29 1.1 christos #endif
30 1.1 christos
31 1.1 christos #ifdef HAVE_STDINT_H
32 1.1 christos #include <stdint.h>
33 1.1 christos #endif
34 1.1 christos
35 1.1 christos #ifdef HAVE_STRING_H
36 1.1 christos #include <string.h>
37 1.1 christos #endif
38 1.1 christos
39 1.1 christos #ifdef HAVE_INTTYPES_H
40 1.1 christos #include <inttypes.h>
41 1.1 christos #endif
42 1.1 christos
43 1.1 christos #ifndef SEEK_SET
44 1.1 christos #define SEEK_SET 0
45 1.1 christos #endif
46 1.1 christos
47 1.1.1.6 christos #ifndef O_BINARY
48 1.1.1.6 christos #define O_BINARY 0
49 1.1.1.6 christos #endif
50 1.1.1.6 christos
51 1.1 christos #include "simple-object-common.h"
52 1.1 christos
53 1.1 christos /* The known object file formats. */
54 1.1 christos
55 1.1 christos static const struct simple_object_functions * const format_functions[] =
56 1.1 christos {
57 1.1 christos &simple_object_elf_functions,
58 1.1 christos &simple_object_mach_o_functions,
59 1.1.1.3 christos &simple_object_coff_functions,
60 1.1.1.3 christos &simple_object_xcoff_functions
61 1.1 christos };
62 1.1 christos
63 1.1 christos /* Read data from a file using the simple_object error reporting
64 1.1 christos conventions. */
65 1.1 christos
66 1.1 christos int
67 1.1 christos simple_object_internal_read (int descriptor, off_t offset,
68 1.1 christos unsigned char *buffer, size_t size,
69 1.1 christos const char **errmsg, int *err)
70 1.1 christos {
71 1.1 christos if (lseek (descriptor, offset, SEEK_SET) < 0)
72 1.1 christos {
73 1.1 christos *errmsg = "lseek";
74 1.1 christos *err = errno;
75 1.1 christos return 0;
76 1.1 christos }
77 1.1 christos
78 1.1.1.3 christos do
79 1.1 christos {
80 1.1.1.3 christos ssize_t got = read (descriptor, buffer, size);
81 1.1.1.3 christos if (got == 0)
82 1.1.1.3 christos break;
83 1.1.1.3 christos else if (got > 0)
84 1.1.1.3 christos {
85 1.1.1.3 christos buffer += got;
86 1.1.1.3 christos size -= got;
87 1.1.1.3 christos }
88 1.1.1.3 christos else if (errno != EINTR)
89 1.1.1.3 christos {
90 1.1.1.3 christos *errmsg = "read";
91 1.1.1.3 christos *err = errno;
92 1.1.1.3 christos return 0;
93 1.1.1.3 christos }
94 1.1 christos }
95 1.1.1.3 christos while (size > 0);
96 1.1 christos
97 1.1.1.3 christos if (size > 0)
98 1.1 christos {
99 1.1 christos *errmsg = "file too short";
100 1.1 christos *err = 0;
101 1.1 christos return 0;
102 1.1 christos }
103 1.1 christos
104 1.1 christos return 1;
105 1.1 christos }
106 1.1 christos
107 1.1 christos /* Write data to a file using the simple_object error reporting
108 1.1 christos conventions. */
109 1.1 christos
110 1.1 christos int
111 1.1 christos simple_object_internal_write (int descriptor, off_t offset,
112 1.1 christos const unsigned char *buffer, size_t size,
113 1.1 christos const char **errmsg, int *err)
114 1.1 christos {
115 1.1 christos if (lseek (descriptor, offset, SEEK_SET) < 0)
116 1.1 christos {
117 1.1 christos *errmsg = "lseek";
118 1.1 christos *err = errno;
119 1.1 christos return 0;
120 1.1 christos }
121 1.1 christos
122 1.1.1.3 christos do
123 1.1 christos {
124 1.1.1.3 christos ssize_t wrote = write (descriptor, buffer, size);
125 1.1.1.3 christos if (wrote == 0)
126 1.1.1.3 christos break;
127 1.1.1.3 christos else if (wrote > 0)
128 1.1.1.3 christos {
129 1.1.1.3 christos buffer += wrote;
130 1.1.1.3 christos size -= wrote;
131 1.1.1.3 christos }
132 1.1.1.3 christos else if (errno != EINTR)
133 1.1.1.3 christos {
134 1.1.1.3 christos *errmsg = "write";
135 1.1.1.3 christos *err = errno;
136 1.1.1.3 christos return 0;
137 1.1.1.3 christos }
138 1.1 christos }
139 1.1.1.3 christos while (size > 0);
140 1.1 christos
141 1.1.1.3 christos if (size > 0)
142 1.1 christos {
143 1.1 christos *errmsg = "short write";
144 1.1 christos *err = 0;
145 1.1 christos return 0;
146 1.1 christos }
147 1.1 christos
148 1.1 christos return 1;
149 1.1 christos }
150 1.1 christos
151 1.1 christos /* Open for read. */
152 1.1 christos
153 1.1 christos simple_object_read *
154 1.1 christos simple_object_start_read (int descriptor, off_t offset,
155 1.1 christos const char *segment_name, const char **errmsg,
156 1.1 christos int *err)
157 1.1 christos {
158 1.1 christos unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
159 1.1 christos size_t len, i;
160 1.1 christos
161 1.1 christos if (!simple_object_internal_read (descriptor, offset, header,
162 1.1 christos SIMPLE_OBJECT_MATCH_HEADER_LEN,
163 1.1 christos errmsg, err))
164 1.1 christos return NULL;
165 1.1 christos
166 1.1 christos len = sizeof (format_functions) / sizeof (format_functions[0]);
167 1.1 christos for (i = 0; i < len; ++i)
168 1.1 christos {
169 1.1 christos void *data;
170 1.1 christos
171 1.1 christos data = format_functions[i]->match (header, descriptor, offset,
172 1.1 christos segment_name, errmsg, err);
173 1.1 christos if (data != NULL)
174 1.1 christos {
175 1.1 christos simple_object_read *ret;
176 1.1 christos
177 1.1 christos ret = XNEW (simple_object_read);
178 1.1 christos ret->descriptor = descriptor;
179 1.1 christos ret->offset = offset;
180 1.1 christos ret->functions = format_functions[i];
181 1.1 christos ret->data = data;
182 1.1 christos return ret;
183 1.1 christos }
184 1.1 christos }
185 1.1 christos
186 1.1 christos *errmsg = "file not recognized";
187 1.1 christos *err = 0;
188 1.1 christos return NULL;
189 1.1 christos }
190 1.1 christos
191 1.1 christos /* Find all sections. */
192 1.1 christos
193 1.1 christos const char *
194 1.1 christos simple_object_find_sections (simple_object_read *sobj,
195 1.1 christos int (*pfn) (void *, const char *, off_t, off_t),
196 1.1 christos void *data,
197 1.1 christos int *err)
198 1.1 christos {
199 1.1 christos return sobj->functions->find_sections (sobj, pfn, data, err);
200 1.1 christos }
201 1.1 christos
202 1.1 christos /* Internal data passed to find_one_section. */
203 1.1 christos
204 1.1 christos struct find_one_section_data
205 1.1 christos {
206 1.1 christos /* The section we are looking for. */
207 1.1 christos const char *name;
208 1.1 christos /* Where to store the section offset. */
209 1.1 christos off_t *offset;
210 1.1 christos /* Where to store the section length. */
211 1.1 christos off_t *length;
212 1.1 christos /* Set if the name is found. */
213 1.1 christos int found;
214 1.1 christos };
215 1.1 christos
216 1.1 christos /* Internal function passed to find_sections. */
217 1.1 christos
218 1.1 christos static int
219 1.1 christos find_one_section (void *data, const char *name, off_t offset, off_t length)
220 1.1 christos {
221 1.1 christos struct find_one_section_data *fosd = (struct find_one_section_data *) data;
222 1.1 christos
223 1.1 christos if (strcmp (name, fosd->name) != 0)
224 1.1 christos return 1;
225 1.1 christos
226 1.1 christos *fosd->offset = offset;
227 1.1 christos *fosd->length = length;
228 1.1 christos fosd->found = 1;
229 1.1 christos
230 1.1 christos /* Stop iteration. */
231 1.1 christos return 0;
232 1.1 christos }
233 1.1 christos
234 1.1 christos /* Find a section. */
235 1.1 christos
236 1.1 christos int
237 1.1 christos simple_object_find_section (simple_object_read *sobj, const char *name,
238 1.1 christos off_t *offset, off_t *length,
239 1.1 christos const char **errmsg, int *err)
240 1.1 christos {
241 1.1 christos struct find_one_section_data fosd;
242 1.1 christos
243 1.1 christos fosd.name = name;
244 1.1 christos fosd.offset = offset;
245 1.1 christos fosd.length = length;
246 1.1 christos fosd.found = 0;
247 1.1 christos
248 1.1 christos *errmsg = simple_object_find_sections (sobj, find_one_section,
249 1.1 christos (void *) &fosd, err);
250 1.1 christos if (*errmsg != NULL)
251 1.1 christos return 0;
252 1.1 christos if (!fosd.found)
253 1.1 christos return 0;
254 1.1 christos return 1;
255 1.1 christos }
256 1.1 christos
257 1.1.1.4 christos /* Callback to identify and rename LTO debug sections by name.
258 1.1.1.5 christos Returns non-NULL if NAME is a LTO debug section, NULL if not.
259 1.1.1.5 christos If RENAME is true it will rename LTO debug sections to non-LTO
260 1.1.1.5 christos ones. */
261 1.1.1.4 christos
262 1.1.1.5 christos static char *
263 1.1.1.5 christos handle_lto_debug_sections (const char *name, int rename)
264 1.1.1.4 christos {
265 1.1.1.5 christos char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
266 1.1.1.5 christos : xstrdup (name);
267 1.1.1.5 christos
268 1.1.1.4 christos /* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
269 1.1.1.4 christos complains about bogus section flags. Which means we need to arrange
270 1.1.1.4 christos for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
271 1.1.1.4 christos fat lto object tooling work for the fat part). */
272 1.1.1.5 christos /* Also include corresponding reloc sections. */
273 1.1.1.5 christos if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
274 1.1.1.5 christos {
275 1.1.1.5 christos if (rename)
276 1.1.1.5 christos strncpy (newname, name, sizeof (".rela") - 1);
277 1.1.1.5 christos name += sizeof (".rela") - 1;
278 1.1.1.5 christos }
279 1.1.1.5 christos else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
280 1.1.1.5 christos {
281 1.1.1.5 christos if (rename)
282 1.1.1.5 christos strncpy (newname, name, sizeof (".rel") - 1);
283 1.1.1.5 christos name += sizeof (".rel") - 1;
284 1.1.1.5 christos }
285 1.1.1.4 christos /* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
286 1.1.1.4 christos sections. */
287 1.1.1.4 christos /* Copy LTO debug sections and rename them to their non-LTO name. */
288 1.1.1.5 christos if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
289 1.1.1.5 christos return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
290 1.1.1.5 christos else if (strncmp (name, ".gnu.lto_.debug_",
291 1.1.1.5 christos sizeof (".gnu.lto_.debug_") -1) == 0)
292 1.1.1.5 christos return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
293 1.1.1.4 christos /* Copy over .note.GNU-stack section under the same name if present. */
294 1.1.1.5 christos else if (strcmp (name, ".note.GNU-stack") == 0)
295 1.1.1.5 christos return strcpy (newname, name);
296 1.1.1.7 christos /* Copy over .note.gnu.property section under the same name if present. */
297 1.1.1.7 christos else if (strcmp (name, ".note.gnu.property") == 0)
298 1.1.1.7 christos return strcpy (newname, name);
299 1.1.1.5 christos /* Copy over .comment section under the same name if present. Solaris
300 1.1.1.5 christos ld uses them to relax its checking of ELF gABI access rules for
301 1.1.1.5 christos COMDAT sections in objects produced by GCC. */
302 1.1.1.5 christos else if (strcmp (name, ".comment") == 0)
303 1.1.1.5 christos return strcpy (newname, name);
304 1.1.1.7 christos /* Copy over .GCC.command.line section under the same name if present. */
305 1.1.1.7 christos else if (strcmp (name, ".GCC.command.line") == 0)
306 1.1.1.7 christos return strcpy (newname, name);
307 1.1.1.7 christos /* Copy over .ctf section under the same name if present. */
308 1.1.1.7 christos else if (strcmp (name, ".ctf") == 0)
309 1.1.1.7 christos return strcpy (newname, name);
310 1.1.1.7 christos /* Copy over .BTF section under the same name if present. */
311 1.1.1.7 christos else if (strcmp (name, ".BTF") == 0)
312 1.1.1.7 christos return strcpy (newname, name);
313 1.1.1.5 christos free (newname);
314 1.1.1.5 christos return NULL;
315 1.1.1.5 christos }
316 1.1.1.5 christos
317 1.1.1.5 christos /* Wrapper for handle_lto_debug_sections. */
318 1.1.1.5 christos
319 1.1.1.5 christos static char *
320 1.1.1.5 christos handle_lto_debug_sections_rename (const char *name)
321 1.1.1.5 christos {
322 1.1.1.5 christos return handle_lto_debug_sections (name, 1);
323 1.1.1.5 christos }
324 1.1.1.5 christos
325 1.1.1.5 christos /* Wrapper for handle_lto_debug_sections. */
326 1.1.1.5 christos
327 1.1.1.5 christos static char *
328 1.1.1.5 christos handle_lto_debug_sections_norename (const char *name)
329 1.1.1.5 christos {
330 1.1.1.5 christos return handle_lto_debug_sections (name, 0);
331 1.1.1.4 christos }
332 1.1.1.4 christos
333 1.1.1.4 christos /* Copy LTO debug sections. */
334 1.1.1.4 christos
335 1.1.1.4 christos const char *
336 1.1.1.4 christos simple_object_copy_lto_debug_sections (simple_object_read *sobj,
337 1.1.1.5 christos const char *dest, int *err, int rename)
338 1.1.1.4 christos {
339 1.1.1.4 christos const char *errmsg;
340 1.1.1.4 christos simple_object_write *dest_sobj;
341 1.1.1.4 christos simple_object_attributes *attrs;
342 1.1.1.4 christos int outfd;
343 1.1.1.4 christos
344 1.1.1.4 christos if (! sobj->functions->copy_lto_debug_sections)
345 1.1.1.4 christos {
346 1.1.1.4 christos *err = EINVAL;
347 1.1.1.4 christos return "simple_object_copy_lto_debug_sections not implemented";
348 1.1.1.4 christos }
349 1.1.1.4 christos
350 1.1.1.4 christos attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
351 1.1.1.4 christos if (! attrs)
352 1.1.1.4 christos return errmsg;
353 1.1.1.4 christos dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
354 1.1.1.4 christos simple_object_release_attributes (attrs);
355 1.1.1.4 christos if (! dest_sobj)
356 1.1.1.4 christos return errmsg;
357 1.1.1.4 christos
358 1.1.1.5 christos errmsg = sobj->functions->copy_lto_debug_sections
359 1.1.1.5 christos (sobj, dest_sobj,
360 1.1.1.5 christos rename ? handle_lto_debug_sections_rename
361 1.1.1.5 christos : handle_lto_debug_sections_norename, err);
362 1.1.1.4 christos if (errmsg)
363 1.1.1.4 christos {
364 1.1.1.4 christos simple_object_release_write (dest_sobj);
365 1.1.1.4 christos return errmsg;
366 1.1.1.4 christos }
367 1.1.1.4 christos
368 1.1.1.6 christos outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
369 1.1.1.4 christos if (outfd == -1)
370 1.1.1.4 christos {
371 1.1.1.4 christos *err = errno;
372 1.1.1.4 christos simple_object_release_write (dest_sobj);
373 1.1.1.4 christos return "open failed";
374 1.1.1.4 christos }
375 1.1.1.4 christos
376 1.1.1.4 christos errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
377 1.1.1.4 christos close (outfd);
378 1.1.1.4 christos if (errmsg)
379 1.1.1.4 christos {
380 1.1.1.4 christos simple_object_release_write (dest_sobj);
381 1.1.1.4 christos return errmsg;
382 1.1.1.4 christos }
383 1.1.1.4 christos
384 1.1.1.4 christos simple_object_release_write (dest_sobj);
385 1.1.1.4 christos return NULL;
386 1.1.1.4 christos }
387 1.1.1.4 christos
388 1.1 christos /* Fetch attributes. */
389 1.1 christos
390 1.1 christos simple_object_attributes *
391 1.1 christos simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
392 1.1 christos int *err)
393 1.1 christos {
394 1.1 christos void *data;
395 1.1 christos simple_object_attributes *ret;
396 1.1 christos
397 1.1 christos data = sobj->functions->fetch_attributes (sobj, errmsg, err);
398 1.1 christos if (data == NULL)
399 1.1 christos return NULL;
400 1.1 christos ret = XNEW (simple_object_attributes);
401 1.1 christos ret->functions = sobj->functions;
402 1.1 christos ret->data = data;
403 1.1 christos return ret;
404 1.1 christos }
405 1.1 christos
406 1.1 christos /* Release an simple_object_read. */
407 1.1 christos
408 1.1 christos void
409 1.1 christos simple_object_release_read (simple_object_read *sobj)
410 1.1 christos {
411 1.1 christos sobj->functions->release_read (sobj->data);
412 1.1 christos XDELETE (sobj);
413 1.1 christos }
414 1.1 christos
415 1.1.1.2 christos /* Merge attributes. */
416 1.1 christos
417 1.1 christos const char *
418 1.1.1.2 christos simple_object_attributes_merge (simple_object_attributes *to,
419 1.1.1.2 christos simple_object_attributes *from,
420 1.1.1.2 christos int *err)
421 1.1 christos {
422 1.1.1.2 christos if (to->functions != from->functions)
423 1.1 christos {
424 1.1 christos *err = 0;
425 1.1 christos return "different object file format";
426 1.1 christos }
427 1.1.1.2 christos return to->functions->attributes_merge (to->data, from->data, err);
428 1.1 christos }
429 1.1 christos
430 1.1 christos /* Release an attributes structure. */
431 1.1 christos
432 1.1 christos void
433 1.1 christos simple_object_release_attributes (simple_object_attributes *attrs)
434 1.1 christos {
435 1.1 christos attrs->functions->release_attributes (attrs->data);
436 1.1 christos XDELETE (attrs);
437 1.1 christos }
438 1.1 christos
439 1.1 christos /* Start creating an object file. */
440 1.1 christos
441 1.1 christos simple_object_write *
442 1.1 christos simple_object_start_write (simple_object_attributes *attrs,
443 1.1 christos const char *segment_name, const char **errmsg,
444 1.1 christos int *err)
445 1.1 christos {
446 1.1 christos void *data;
447 1.1 christos simple_object_write *ret;
448 1.1 christos
449 1.1 christos data = attrs->functions->start_write (attrs->data, errmsg, err);
450 1.1 christos if (data == NULL)
451 1.1 christos return NULL;
452 1.1 christos ret = XNEW (simple_object_write);
453 1.1 christos ret->functions = attrs->functions;
454 1.1.1.4 christos ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
455 1.1 christos ret->sections = NULL;
456 1.1 christos ret->last_section = NULL;
457 1.1 christos ret->data = data;
458 1.1 christos return ret;
459 1.1 christos }
460 1.1 christos
461 1.1 christos /* Start creating a section. */
462 1.1 christos
463 1.1 christos simple_object_write_section *
464 1.1 christos simple_object_write_create_section (simple_object_write *sobj, const char *name,
465 1.1 christos unsigned int align,
466 1.1 christos const char **errmsg ATTRIBUTE_UNUSED,
467 1.1 christos int *err ATTRIBUTE_UNUSED)
468 1.1 christos {
469 1.1 christos simple_object_write_section *ret;
470 1.1 christos
471 1.1 christos ret = XNEW (simple_object_write_section);
472 1.1 christos ret->next = NULL;
473 1.1 christos ret->name = xstrdup (name);
474 1.1 christos ret->align = align;
475 1.1 christos ret->buffers = NULL;
476 1.1 christos ret->last_buffer = NULL;
477 1.1 christos
478 1.1 christos if (sobj->last_section == NULL)
479 1.1 christos {
480 1.1 christos sobj->sections = ret;
481 1.1 christos sobj->last_section = ret;
482 1.1 christos }
483 1.1 christos else
484 1.1 christos {
485 1.1 christos sobj->last_section->next = ret;
486 1.1 christos sobj->last_section = ret;
487 1.1 christos }
488 1.1 christos
489 1.1 christos return ret;
490 1.1 christos }
491 1.1 christos
492 1.1 christos /* Add data to a section. */
493 1.1 christos
494 1.1 christos const char *
495 1.1 christos simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
496 1.1 christos simple_object_write_section *section,
497 1.1 christos const void *buffer,
498 1.1 christos size_t size, int copy,
499 1.1 christos int *err ATTRIBUTE_UNUSED)
500 1.1 christos {
501 1.1 christos struct simple_object_write_section_buffer *wsb;
502 1.1 christos
503 1.1 christos wsb = XNEW (struct simple_object_write_section_buffer);
504 1.1 christos wsb->next = NULL;
505 1.1 christos wsb->size = size;
506 1.1 christos
507 1.1 christos if (!copy)
508 1.1 christos {
509 1.1 christos wsb->buffer = buffer;
510 1.1 christos wsb->free_buffer = NULL;
511 1.1 christos }
512 1.1 christos else
513 1.1 christos {
514 1.1 christos wsb->free_buffer = (void *) XNEWVEC (char, size);
515 1.1 christos memcpy (wsb->free_buffer, buffer, size);
516 1.1 christos wsb->buffer = wsb->free_buffer;
517 1.1 christos }
518 1.1 christos
519 1.1 christos if (section->last_buffer == NULL)
520 1.1 christos {
521 1.1 christos section->buffers = wsb;
522 1.1 christos section->last_buffer = wsb;
523 1.1 christos }
524 1.1 christos else
525 1.1 christos {
526 1.1 christos section->last_buffer->next = wsb;
527 1.1 christos section->last_buffer = wsb;
528 1.1 christos }
529 1.1 christos
530 1.1 christos return NULL;
531 1.1 christos }
532 1.1 christos
533 1.1 christos /* Write the complete object file. */
534 1.1 christos
535 1.1 christos const char *
536 1.1 christos simple_object_write_to_file (simple_object_write *sobj, int descriptor,
537 1.1 christos int *err)
538 1.1 christos {
539 1.1 christos return sobj->functions->write_to_file (sobj, descriptor, err);
540 1.1 christos }
541 1.1 christos
542 1.1 christos /* Release an simple_object_write. */
543 1.1 christos
544 1.1 christos void
545 1.1 christos simple_object_release_write (simple_object_write *sobj)
546 1.1 christos {
547 1.1 christos simple_object_write_section *section;
548 1.1 christos
549 1.1 christos free (sobj->segment_name);
550 1.1 christos
551 1.1 christos section = sobj->sections;
552 1.1 christos while (section != NULL)
553 1.1 christos {
554 1.1 christos struct simple_object_write_section_buffer *buffer;
555 1.1 christos simple_object_write_section *next_section;
556 1.1 christos
557 1.1 christos buffer = section->buffers;
558 1.1 christos while (buffer != NULL)
559 1.1 christos {
560 1.1 christos struct simple_object_write_section_buffer *next_buffer;
561 1.1 christos
562 1.1 christos if (buffer->free_buffer != NULL)
563 1.1 christos XDELETEVEC (buffer->free_buffer);
564 1.1 christos next_buffer = buffer->next;
565 1.1 christos XDELETE (buffer);
566 1.1 christos buffer = next_buffer;
567 1.1 christos }
568 1.1 christos
569 1.1 christos next_section = section->next;
570 1.1 christos free (section->name);
571 1.1 christos XDELETE (section);
572 1.1 christos section = next_section;
573 1.1 christos }
574 1.1 christos
575 1.1 christos sobj->functions->release_write (sobj->data);
576 1.1 christos XDELETE (sobj);
577 1.1 christos }
578