1 1.1 christos /* simple-object.c -- simple routines to read and write object files. 2 1.1.1.10 christos Copyright (C) 2010-2026 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