1 1.1 christos /* simple-object-coff.c -- routines to manipulate XCOFF object files. 2 1.1.1.8 christos Copyright (C) 2013-2026 Free Software Foundation, Inc. 3 1.1 christos Written by Ian Lance Taylor, Google and David Edelsohn, IBM. 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 christos #include <stddef.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 #include "simple-object-common.h" 44 1.1 christos 45 1.1 christos /* XCOFF structures and constants. */ 46 1.1 christos 47 1.1 christos /* XCOFF file header. */ 48 1.1 christos 49 1.1 christos struct external_filehdr 50 1.1 christos { 51 1.1 christos unsigned char f_magic[2]; /* magic number */ 52 1.1 christos unsigned char f_nscns[2]; /* number of sections */ 53 1.1 christos unsigned char f_timdat[4]; /* time & date stamp */ 54 1.1 christos union 55 1.1 christos { 56 1.1 christos struct 57 1.1 christos { 58 1.1 christos unsigned char f_symptr[4]; /* file pointer to symtab */ 59 1.1 christos unsigned char f_nsyms[4]; /* number of symtab entries */ 60 1.1 christos unsigned char f_opthdr[2]; /* sizeof(optional hdr) */ 61 1.1 christos unsigned char f_flags[2]; /* flags */ 62 1.1 christos } xcoff32; 63 1.1 christos struct 64 1.1 christos { 65 1.1 christos unsigned char f_symptr[8]; /* file pointer to symtab */ 66 1.1 christos unsigned char f_opthdr[2]; /* sizeof(optional hdr) */ 67 1.1 christos unsigned char f_flags[2]; /* flags */ 68 1.1 christos unsigned char f_nsyms[4]; /* number of symtab entries */ 69 1.1 christos } xcoff64; 70 1.1 christos } u; 71 1.1 christos }; 72 1.1 christos 73 1.1 christos /* Bits for filehdr f_flags field. */ 74 1.1 christos 75 1.1 christos #define F_EXEC (0x0002) 76 1.1 christos 77 1.1 christos /* The known values of f_magic in an XCOFF file header. */ 78 1.1 christos 79 1.1 christos #define U802WRMAGIC 0730 /* Writeable text segments. */ 80 1.1 christos #define U802ROMAGIC 0735 /* Readonly sharable text segments. */ 81 1.1 christos #define U802TOCMAGIC 0737 /* Readonly text segments and TOC. */ 82 1.1 christos #define U803XTOCMAGIC 0757 /* Aix 4.3 64-bit XCOFF. */ 83 1.1 christos #define U64_TOCMAGIC 0767 /* AIX 5+ 64-bit XCOFF. */ 84 1.1 christos 85 1.1 christos /* XCOFF section header. */ 86 1.1 christos 87 1.1 christos struct external_scnhdr 88 1.1 christos { 89 1.1 christos unsigned char s_name[8]; /* section name */ 90 1.1 christos union 91 1.1 christos { 92 1.1 christos struct 93 1.1 christos { 94 1.1 christos unsigned char s_paddr[4]; /* physical address, aliased s_nlib */ 95 1.1 christos unsigned char s_vaddr[4]; /* virtual address */ 96 1.1 christos unsigned char s_size[4]; /* section size */ 97 1.1 christos unsigned char s_scnptr[4]; /* file ptr to raw data for section */ 98 1.1 christos unsigned char s_relptr[4]; /* file ptr to relocation */ 99 1.1 christos unsigned char s_lnnoptr[4]; /* file ptr to line numbers */ 100 1.1 christos unsigned char s_nreloc[2]; /* number of relocation entries */ 101 1.1 christos unsigned char s_nlnno[2]; /* number of line number entries */ 102 1.1 christos unsigned char s_flags[4]; /* flags */ 103 1.1 christos } xcoff32; 104 1.1 christos struct 105 1.1 christos { 106 1.1 christos unsigned char s_paddr[8]; /* physical address, aliased s_nlib */ 107 1.1 christos unsigned char s_vaddr[8]; /* virtual address */ 108 1.1 christos unsigned char s_size[8]; /* section size */ 109 1.1 christos unsigned char s_scnptr[8]; /* file ptr to raw data for section */ 110 1.1 christos unsigned char s_relptr[8]; /* file ptr to relocation */ 111 1.1 christos unsigned char s_lnnoptr[8]; /* file ptr to line numbers */ 112 1.1 christos unsigned char s_nreloc[4]; /* number of relocation entries */ 113 1.1 christos unsigned char s_nlnno[4]; /* number of line number entries */ 114 1.1 christos unsigned char s_flags[4]; /* flags */ 115 1.1 christos } xcoff64; 116 1.1 christos } u; 117 1.1 christos }; 118 1.1 christos 119 1.1 christos #define SCNHSZ32 (40) 120 1.1 christos #define SCNHSZ64 (68) 121 1.1 christos 122 1.1 christos /* The length of the s_name field in struct external_scnhdr. */ 123 1.1 christos 124 1.1 christos #define SCNNMLEN (8) 125 1.1 christos 126 1.1 christos /* Bits for scnhdr s_flags field. */ 127 1.1 christos 128 1.1 christos #define STYP_DATA 0x40 129 1.1 christos 130 1.1 christos /* XCOFF symbol table entry. */ 131 1.1 christos 132 1.1 christos 133 1.1 christos #define N_SYMNMLEN (8) /* # characters in a symbol name */ 134 1.1 christos 135 1.1 christos /* The format of an XCOFF symbol-table entry. */ 136 1.1 christos struct external_syment 137 1.1 christos { 138 1.1 christos union { 139 1.1 christos struct { 140 1.1 christos union { 141 1.1.1.2 christos /* The name of the symbol. There is an implicit null character 142 1.1.1.2 christos after the end of the array. */ 143 1.1.1.2 christos char n_name[N_SYMNMLEN]; 144 1.1.1.2 christos struct { 145 1.1.1.2 christos /* If n_zeroes is zero, n_offset is the offset the name from 146 1.1.1.2 christos the start of the string table. */ 147 1.1.1.2 christos unsigned char n_zeroes[4]; 148 1.1.1.2 christos unsigned char n_offset[4]; 149 1.1.1.2 christos } n; 150 1.1 christos } n; 151 1.1 christos 152 1.1 christos /* The symbol's value. */ 153 1.1 christos unsigned char n_value[4]; 154 1.1 christos } xcoff32; 155 1.1 christos struct { 156 1.1 christos /* The symbol's value. */ 157 1.1 christos unsigned char n_value[8]; 158 1.1 christos 159 1.1 christos /* The offset of the symbol from the start of the string table. */ 160 1.1 christos unsigned char n_offset[4]; 161 1.1 christos } xcoff64; 162 1.1 christos } u; 163 1.1 christos 164 1.1 christos /* The number of the section to which this symbol belongs. */ 165 1.1 christos unsigned char n_scnum[2]; 166 1.1 christos 167 1.1 christos /* The type of symbol. (It can be interpreted as an n_lang 168 1.1 christos and an n_cpu byte, but we don't care about that here.) */ 169 1.1 christos unsigned char n_type[2]; 170 1.1 christos 171 1.1 christos /* The class of symbol (a C_* value). */ 172 1.1 christos unsigned char n_sclass[1]; 173 1.1 christos 174 1.1 christos /* The number of auxiliary symbols attached to this entry. */ 175 1.1 christos unsigned char n_numaux[1]; 176 1.1 christos }; 177 1.1 christos 178 1.1 christos #define SYMESZ (18) 179 1.1 christos 180 1.1 christos /* Length allowed for filename in aux sym format 4. */ 181 1.1 christos 182 1.1 christos #define FILNMLEN (14) 183 1.1 christos 184 1.1 christos /* Omits x_sym and other unused variants. */ 185 1.1 christos 186 1.1 christos union external_auxent 187 1.1 christos { 188 1.1 christos /* Aux sym format 4: file. */ 189 1.1 christos union 190 1.1 christos { 191 1.1 christos char x_fname[FILNMLEN]; 192 1.1 christos struct 193 1.1 christos { 194 1.1 christos unsigned char x_zeroes[4]; 195 1.1 christos unsigned char x_offset[4]; 196 1.1 christos unsigned char x_pad[FILNMLEN-8]; 197 1.1 christos unsigned char x_ftype; 198 1.1 christos } _x; 199 1.1 christos } x_file; 200 1.1 christos /* Aux sym format 5: section. */ 201 1.1 christos struct 202 1.1 christos { 203 1.1 christos unsigned char x_scnlen[4]; /* section length */ 204 1.1 christos unsigned char x_nreloc[2]; /* # relocation entries */ 205 1.1 christos unsigned char x_nlinno[2]; /* # line numbers */ 206 1.1 christos } x_scn; 207 1.1 christos /* CSECT auxiliary entry. */ 208 1.1 christos union 209 1.1 christos { 210 1.1 christos struct 211 1.1 christos { 212 1.1 christos struct 213 1.1 christos { 214 1.1 christos unsigned char x_scnlen[4]; /* csect length */ 215 1.1 christos unsigned char x_parmhash[4]; /* parm type hash index */ 216 1.1 christos unsigned char x_snhash[2]; /* sect num with parm hash */ 217 1.1 christos unsigned char x_smtyp; /* symbol align and type */ 218 1.1 christos unsigned char x_smclas; /* storage mapping class */ 219 1.1 christos unsigned char x_stab; /* dbx stab info index */ 220 1.1 christos unsigned char x_snstab[2]; /* sect num with dbx stab */ 221 1.1 christos } x_csect; 222 1.1 christos } xcoff32; 223 1.1 christos struct 224 1.1 christos { 225 1.1 christos struct 226 1.1 christos { 227 1.1 christos unsigned char x_scnlen_lo[4]; /* csect length */ 228 1.1 christos unsigned char x_parmhash[4]; /* parm type hash index */ 229 1.1 christos unsigned char x_snhash[2]; /* sect num with parm hash */ 230 1.1 christos unsigned char x_smtyp; /* symbol align and type */ 231 1.1 christos unsigned char x_smclas; /* storage mapping class */ 232 1.1 christos unsigned char x_scnlen_hi[4]; 233 1.1 christos unsigned char pad; 234 1.1 christos unsigned char x_auxtype; 235 1.1 christos } x_csect; 236 1.1 christos } xcoff64; 237 1.1 christos } u; 238 1.1 christos /* SECTION/DWARF auxiliary entry. */ 239 1.1 christos struct 240 1.1 christos { 241 1.1 christos unsigned char x_scnlen[4]; /* section length */ 242 1.1 christos unsigned char pad1[4]; 243 1.1 christos unsigned char x_nreloc[4]; /* number RLDs */ 244 1.1 christos } x_sect; 245 1.1 christos }; 246 1.1 christos 247 1.1 christos /* Symbol-related constants. */ 248 1.1 christos 249 1.1 christos #define N_DEBUG (-2) 250 1.1 christos #define IMAGE_SYM_TYPE_NULL (0) 251 1.1 christos #define IMAGE_SYM_DTYPE_NULL (0) 252 1.1 christos #define IMAGE_SYM_CLASS_STATIC (3) 253 1.1 christos #define IMAGE_SYM_CLASS_FILE (103) 254 1.1 christos 255 1.1 christos #define IMAGE_SYM_TYPE \ 256 1.1 christos ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL) 257 1.1 christos 258 1.1.1.2 christos #define C_EXT (2) 259 1.1 christos #define C_STAT (3) 260 1.1 christos #define C_FILE (103) 261 1.1.1.2 christos #define C_HIDEXT (107) 262 1.1.1.2 christos 263 1.1.1.2 christos #define XTY_SD (1) /* section definition */ 264 1.1.1.2 christos 265 1.1.1.2 christos #define XMC_XO (7) /* extended operation */ 266 1.1 christos 267 1.1 christos /* Private data for an simple_object_read. */ 268 1.1 christos 269 1.1 christos struct simple_object_xcoff_read 270 1.1 christos { 271 1.1 christos /* Magic number. */ 272 1.1 christos unsigned short magic; 273 1.1 christos /* Number of sections. */ 274 1.1 christos unsigned short nscns; 275 1.1 christos /* File offset of symbol table. */ 276 1.1 christos off_t symptr; 277 1.1 christos /* Number of symbol table entries. */ 278 1.1 christos unsigned int nsyms; 279 1.1 christos /* Flags. */ 280 1.1 christos unsigned short flags; 281 1.1 christos /* Offset of section headers in file. */ 282 1.1 christos off_t scnhdr_offset; 283 1.1 christos }; 284 1.1 christos 285 1.1 christos /* Private data for an simple_object_attributes. */ 286 1.1 christos 287 1.1 christos struct simple_object_xcoff_attributes 288 1.1 christos { 289 1.1 christos /* Magic number. */ 290 1.1 christos unsigned short magic; 291 1.1 christos /* Flags. */ 292 1.1 christos unsigned short flags; 293 1.1 christos }; 294 1.1 christos 295 1.1 christos /* See if we have a XCOFF file. */ 296 1.1 christos 297 1.1 christos static void * 298 1.1 christos simple_object_xcoff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN], 299 1.1 christos int descriptor, off_t offset, 300 1.1 christos const char *segment_name ATTRIBUTE_UNUSED, 301 1.1 christos const char **errmsg, int *err) 302 1.1 christos { 303 1.1 christos unsigned short magic; 304 1.1 christos unsigned short (*fetch_16) (const unsigned char *); 305 1.1 christos unsigned int (*fetch_32) (const unsigned char *); 306 1.1 christos ulong_type (*fetch_64) (const unsigned char *); 307 1.1 christos unsigned char hdrbuf[sizeof (struct external_filehdr)]; 308 1.1 christos struct simple_object_xcoff_read *ocr; 309 1.1 christos int u64; 310 1.1 christos 311 1.1 christos magic = simple_object_fetch_big_16 (header); 312 1.1 christos 313 1.1 christos if (magic != U802TOCMAGIC && magic != U64_TOCMAGIC) 314 1.1 christos { 315 1.1 christos *errmsg = NULL; 316 1.1 christos *err = 0; 317 1.1 christos return NULL; 318 1.1 christos } 319 1.1 christos 320 1.1 christos fetch_16 = simple_object_fetch_big_16; 321 1.1 christos fetch_32 = simple_object_fetch_big_32; 322 1.1 christos fetch_64 = simple_object_fetch_big_64; 323 1.1 christos 324 1.1 christos if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf, 325 1.1 christos errmsg, err)) 326 1.1 christos return NULL; 327 1.1 christos 328 1.1 christos u64 = magic == U64_TOCMAGIC; 329 1.1 christos 330 1.1 christos ocr = XNEW (struct simple_object_xcoff_read); 331 1.1 christos ocr->magic = magic; 332 1.1 christos ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns)); 333 1.1 christos if (u64) 334 1.1 christos { 335 1.1 christos ocr->symptr = fetch_64 (hdrbuf 336 1.1 christos + offsetof (struct external_filehdr, 337 1.1 christos u.xcoff64.f_symptr)); 338 1.1 christos ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, 339 1.1 christos u.xcoff64.f_nsyms)); 340 1.1 christos ocr->scnhdr_offset = (sizeof (struct external_filehdr) 341 1.1 christos + fetch_16 (hdrbuf + offsetof (struct external_filehdr, 342 1.1 christos u.xcoff64.f_opthdr))); 343 1.1 christos 344 1.1 christos } 345 1.1 christos else 346 1.1 christos { 347 1.1 christos ocr->symptr = fetch_32 (hdrbuf 348 1.1 christos + offsetof (struct external_filehdr, 349 1.1 christos u.xcoff32.f_symptr)); 350 1.1 christos ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, 351 1.1 christos u.xcoff32.f_nsyms)); 352 1.1 christos ocr->scnhdr_offset = (sizeof (struct external_filehdr) - 4 353 1.1 christos + fetch_16 (hdrbuf + offsetof (struct external_filehdr, 354 1.1 christos u.xcoff32.f_opthdr))); 355 1.1 christos 356 1.1 christos } 357 1.1 christos 358 1.1 christos return (void *) ocr; 359 1.1 christos } 360 1.1 christos 361 1.1 christos /* Read the string table in a XCOFF file. */ 362 1.1 christos 363 1.1 christos static char * 364 1.1 christos simple_object_xcoff_read_strtab (simple_object_read *sobj, size_t *strtab_size, 365 1.1 christos const char **errmsg, int *err) 366 1.1 christos { 367 1.1 christos struct simple_object_xcoff_read *ocr = 368 1.1 christos (struct simple_object_xcoff_read *) sobj->data; 369 1.1 christos off_t strtab_offset; 370 1.1 christos unsigned char strsizebuf[4]; 371 1.1 christos size_t strsize; 372 1.1 christos char *strtab; 373 1.1 christos 374 1.1 christos strtab_offset = sobj->offset + ocr->symptr 375 1.1 christos + ocr->nsyms * SYMESZ; 376 1.1 christos if (!simple_object_internal_read (sobj->descriptor, strtab_offset, 377 1.1 christos strsizebuf, 4, errmsg, err)) 378 1.1 christos return NULL; 379 1.1 christos strsize = simple_object_fetch_big_32 (strsizebuf); 380 1.1 christos strtab = XNEWVEC (char, strsize); 381 1.1 christos if (!simple_object_internal_read (sobj->descriptor, strtab_offset, 382 1.1 christos (unsigned char *) strtab, strsize, errmsg, 383 1.1 christos err)) 384 1.1 christos { 385 1.1 christos XDELETEVEC (strtab); 386 1.1 christos return NULL; 387 1.1 christos } 388 1.1 christos *strtab_size = strsize; 389 1.1 christos return strtab; 390 1.1 christos } 391 1.1 christos 392 1.1 christos /* Find all sections in a XCOFF file. */ 393 1.1 christos 394 1.1 christos static const char * 395 1.1 christos simple_object_xcoff_find_sections (simple_object_read *sobj, 396 1.1 christos int (*pfn) (void *, const char *, 397 1.1 christos off_t offset, off_t length), 398 1.1 christos void *data, 399 1.1 christos int *err) 400 1.1 christos { 401 1.1 christos struct simple_object_xcoff_read *ocr = 402 1.1 christos (struct simple_object_xcoff_read *) sobj->data; 403 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC; 404 1.1 christos size_t scnhdr_size; 405 1.1 christos unsigned char *scnbuf; 406 1.1 christos const char *errmsg; 407 1.1.1.2 christos unsigned short (*fetch_16) (const unsigned char *); 408 1.1 christos unsigned int (*fetch_32) (const unsigned char *); 409 1.1 christos ulong_type (*fetch_64) (const unsigned char *); 410 1.1 christos unsigned int nscns; 411 1.1 christos char *strtab; 412 1.1 christos size_t strtab_size; 413 1.1.1.2 christos struct external_syment *symtab = NULL; 414 1.1 christos unsigned int i; 415 1.1 christos 416 1.1 christos scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32; 417 1.1 christos scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns); 418 1.1 christos if (!simple_object_internal_read (sobj->descriptor, 419 1.1 christos sobj->offset + ocr->scnhdr_offset, 420 1.1 christos scnbuf, scnhdr_size * ocr->nscns, &errmsg, 421 1.1 christos err)) 422 1.1 christos { 423 1.1 christos XDELETEVEC (scnbuf); 424 1.1 christos return errmsg; 425 1.1 christos } 426 1.1 christos 427 1.1.1.2 christos fetch_16 = simple_object_fetch_big_16; 428 1.1 christos fetch_32 = simple_object_fetch_big_32; 429 1.1 christos fetch_64 = simple_object_fetch_big_64; 430 1.1 christos 431 1.1 christos nscns = ocr->nscns; 432 1.1 christos strtab = NULL; 433 1.1 christos strtab_size = 0; 434 1.1 christos for (i = 0; i < nscns; ++i) 435 1.1 christos { 436 1.1 christos unsigned char *scnhdr; 437 1.1 christos unsigned char *scnname; 438 1.1 christos char namebuf[SCNNMLEN + 1]; 439 1.1 christos char *name; 440 1.1 christos off_t scnptr; 441 1.1.1.2 christos off_t size; 442 1.1 christos 443 1.1 christos scnhdr = scnbuf + i * scnhdr_size; 444 1.1 christos scnname = scnhdr + offsetof (struct external_scnhdr, s_name); 445 1.1 christos memcpy (namebuf, scnname, SCNNMLEN); 446 1.1 christos namebuf[SCNNMLEN] = '\0'; 447 1.1 christos name = &namebuf[0]; 448 1.1 christos if (namebuf[0] == '/') 449 1.1 christos { 450 1.1 christos size_t strindex; 451 1.1 christos char *end; 452 1.1 christos 453 1.1 christos strindex = strtol (namebuf + 1, &end, 10); 454 1.1 christos if (*end == '\0') 455 1.1 christos { 456 1.1 christos /* The real section name is found in the string 457 1.1 christos table. */ 458 1.1 christos if (strtab == NULL) 459 1.1 christos { 460 1.1 christos strtab = simple_object_xcoff_read_strtab (sobj, 461 1.1 christos &strtab_size, 462 1.1 christos &errmsg, err); 463 1.1 christos if (strtab == NULL) 464 1.1 christos { 465 1.1 christos XDELETEVEC (scnbuf); 466 1.1 christos return errmsg; 467 1.1 christos } 468 1.1 christos } 469 1.1 christos 470 1.1 christos if (strindex < 4 || strindex >= strtab_size) 471 1.1 christos { 472 1.1 christos XDELETEVEC (strtab); 473 1.1 christos XDELETEVEC (scnbuf); 474 1.1 christos *err = 0; 475 1.1 christos return "section string index out of range"; 476 1.1 christos } 477 1.1 christos 478 1.1 christos name = strtab + strindex; 479 1.1 christos } 480 1.1 christos } 481 1.1 christos 482 1.1 christos if (u64) 483 1.1 christos { 484 1.1 christos scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr, 485 1.1 christos u.xcoff64.s_scnptr)); 486 1.1 christos size = fetch_64 (scnhdr + offsetof (struct external_scnhdr, 487 1.1 christos u.xcoff64.s_size)); 488 1.1 christos } 489 1.1 christos else 490 1.1 christos { 491 1.1 christos scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, 492 1.1 christos u.xcoff32.s_scnptr)); 493 1.1 christos size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, 494 1.1 christos u.xcoff32.s_size)); 495 1.1 christos } 496 1.1 christos 497 1.1 christos if (!(*pfn) (data, name, scnptr, size)) 498 1.1 christos break; 499 1.1 christos } 500 1.1 christos 501 1.1.1.2 christos /* Special handling for .go_export csect. */ 502 1.1.1.2 christos if (ocr->nsyms > 0) 503 1.1.1.2 christos { 504 1.1.1.2 christos unsigned char *sym; 505 1.1.1.2 christos const char *n_name; 506 1.1.1.2 christos off_t size, n_value; 507 1.1.1.2 christos unsigned int n_numaux, n_offset, n_zeroes; 508 1.1.1.2 christos short n_scnum; 509 1.1.1.2 christos 510 1.1.1.2 christos /* Read symbol table. */ 511 1.1.1.2 christos symtab = XNEWVEC (struct external_syment, ocr->nsyms * SYMESZ); 512 1.1.1.2 christos if (!simple_object_internal_read (sobj->descriptor, 513 1.1.1.2 christos sobj->offset + ocr->symptr, 514 1.1.1.2 christos (unsigned char *) symtab, 515 1.1.1.2 christos ocr->nsyms * SYMESZ, 516 1.1.1.2 christos &errmsg, err)) 517 1.1.1.2 christos { 518 1.1.1.2 christos XDELETEVEC (symtab); 519 1.1.1.2 christos XDELETEVEC (scnbuf); 520 1.1.1.2 christos return NULL; 521 1.1.1.2 christos } 522 1.1.1.2 christos 523 1.1.1.2 christos /* Search in symbol table if we have a ".go_export" symbol. */ 524 1.1.1.2 christos for (i = 0; i < ocr->nsyms; i += n_numaux + 1) 525 1.1.1.2 christos { 526 1.1.1.2 christos sym = (unsigned char *) &symtab[i]; 527 1.1.1.2 christos n_numaux = symtab[i].n_numaux[0]; 528 1.1.1.2 christos 529 1.1.1.2 christos if (symtab[i].n_sclass[0] != C_EXT 530 1.1.1.2 christos && symtab[i].n_sclass[0] != C_HIDEXT) 531 1.1.1.2 christos continue; 532 1.1.1.2 christos 533 1.1.1.2 christos /* Must have at least one csect auxiliary entry. */ 534 1.1.1.2 christos if (n_numaux < 1 || i + n_numaux >= ocr->nsyms) 535 1.1.1.2 christos continue; 536 1.1.1.2 christos 537 1.1.1.2 christos n_scnum = fetch_16 (sym + offsetof (struct external_syment, 538 1.1.1.2 christos n_scnum)); 539 1.1.1.2 christos if (n_scnum < 1 || (unsigned int) n_scnum > nscns) 540 1.1.1.2 christos continue; 541 1.1.1.2 christos 542 1.1.1.2 christos if (u64) 543 1.1.1.2 christos { 544 1.1.1.2 christos n_value = fetch_64 (sym + offsetof (struct external_syment, 545 1.1.1.2 christos u.xcoff64.n_value)); 546 1.1.1.2 christos n_offset = fetch_32 (sym + offsetof (struct external_syment, 547 1.1.1.2 christos u.xcoff64.n_offset)); 548 1.1.1.2 christos } 549 1.1.1.2 christos else 550 1.1.1.2 christos { 551 1.1.1.2 christos /* ".go_export" is longer than N_SYMNMLEN. */ 552 1.1.1.2 christos n_zeroes = fetch_32 (sym + offsetof (struct external_syment, 553 1.1.1.2 christos u.xcoff32.n.n.n_zeroes)); 554 1.1.1.2 christos if (n_zeroes != 0) 555 1.1.1.2 christos continue; 556 1.1.1.2 christos 557 1.1.1.2 christos n_value = fetch_32 (sym + offsetof (struct external_syment, 558 1.1.1.2 christos u.xcoff32.n_value)); 559 1.1.1.2 christos n_offset = fetch_32 (sym + offsetof (struct external_syment, 560 1.1.1.2 christos u.xcoff32.n.n.n_offset)); 561 1.1.1.2 christos } 562 1.1.1.2 christos 563 1.1.1.2 christos /* The real symbol name is found in the string table. */ 564 1.1.1.2 christos if (strtab == NULL) 565 1.1.1.2 christos { 566 1.1.1.2 christos strtab = simple_object_xcoff_read_strtab (sobj, 567 1.1.1.2 christos &strtab_size, 568 1.1.1.2 christos &errmsg, err); 569 1.1.1.2 christos if (strtab == NULL) 570 1.1.1.2 christos { 571 1.1.1.2 christos XDELETEVEC (symtab); 572 1.1.1.2 christos XDELETEVEC (scnbuf); 573 1.1.1.2 christos return errmsg; 574 1.1.1.2 christos } 575 1.1.1.2 christos } 576 1.1.1.2 christos 577 1.1.1.2 christos if (n_offset >= strtab_size) 578 1.1.1.2 christos { 579 1.1.1.2 christos XDELETEVEC (strtab); 580 1.1.1.2 christos XDELETEVEC (symtab); 581 1.1.1.2 christos XDELETEVEC (scnbuf); 582 1.1.1.2 christos *err = 0; 583 1.1.1.2 christos return "symbol string index out of range"; 584 1.1.1.2 christos } 585 1.1.1.2 christos n_name = strtab + n_offset; 586 1.1.1.2 christos 587 1.1.1.2 christos if (!strcmp (n_name, ".go_export")) 588 1.1.1.2 christos { 589 1.1.1.2 christos union external_auxent *auxent; 590 1.1.1.2 christos unsigned char *aux, *scnhdr; 591 1.1.1.2 christos off_t scnptr, x_scnlen; 592 1.1.1.2 christos 593 1.1.1.2 christos /* Found .go_export symbol, read its csect auxiliary entry. 594 1.1.1.2 christos By convention, it is the last auxiliary entry. */ 595 1.1.1.2 christos auxent = (union external_auxent *) &symtab[i + n_numaux]; 596 1.1.1.2 christos aux = (unsigned char *) auxent; 597 1.1.1.2 christos if (u64) 598 1.1.1.2 christos { 599 1.1.1.3 christos /* Use an intermediate 64-bit type to avoid 600 1.1.1.3 christos compilation warning about 32-bit shift below on 601 1.1.1.3 christos hosts with 32-bit off_t which aren't supported by 602 1.1.1.3 christos AC_SYS_LARGEFILE. */ 603 1.1.1.3 christos ulong_type x_scnlen64; 604 1.1.1.3 christos 605 1.1.1.2 christos if ((auxent->u.xcoff64.x_csect.x_smtyp & 0x7) != XTY_SD 606 1.1.1.2 christos || auxent->u.xcoff64.x_csect.x_smclas != XMC_XO) 607 1.1.1.2 christos continue; 608 1.1.1.2 christos 609 1.1.1.3 christos x_scnlen64 = 610 1.1.1.3 christos fetch_32 (aux + offsetof (union external_auxent, 611 1.1.1.3 christos u.xcoff64.x_csect.x_scnlen_hi)); 612 1.1.1.3 christos x_scnlen = 613 1.1.1.3 christos ((x_scnlen64 << 32) 614 1.1.1.3 christos | fetch_32 (aux 615 1.1.1.3 christos + offsetof (union external_auxent, 616 1.1.1.3 christos u.xcoff64.x_csect.x_scnlen_lo))); 617 1.1.1.2 christos } 618 1.1.1.2 christos else 619 1.1.1.2 christos { 620 1.1.1.2 christos if ((auxent->u.xcoff32.x_csect.x_smtyp & 0x7) != XTY_SD 621 1.1.1.2 christos || auxent->u.xcoff32.x_csect.x_smclas != XMC_XO) 622 1.1.1.2 christos continue; 623 1.1.1.2 christos 624 1.1.1.2 christos x_scnlen = fetch_32 (aux + offsetof (union external_auxent, 625 1.1.1.2 christos u.xcoff32.x_csect.x_scnlen)); 626 1.1.1.2 christos } 627 1.1.1.2 christos 628 1.1.1.2 christos /* Get header of containing section. */ 629 1.1.1.2 christos scnhdr = scnbuf + (n_scnum - 1) * scnhdr_size; 630 1.1.1.2 christos if (u64) 631 1.1.1.2 christos { 632 1.1.1.2 christos scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr, 633 1.1.1.2 christos u.xcoff64.s_scnptr)); 634 1.1.1.2 christos size = fetch_64 (scnhdr + offsetof (struct external_scnhdr, 635 1.1.1.2 christos u.xcoff64.s_size)); 636 1.1.1.2 christos } 637 1.1.1.2 christos else 638 1.1.1.2 christos { 639 1.1.1.2 christos scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, 640 1.1.1.2 christos u.xcoff32.s_scnptr)); 641 1.1.1.2 christos size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, 642 1.1.1.2 christos u.xcoff32.s_size)); 643 1.1.1.2 christos } 644 1.1.1.2 christos if (n_value + x_scnlen > size) 645 1.1.1.2 christos break; 646 1.1.1.2 christos 647 1.1.1.2 christos (*pfn) (data, ".go_export", scnptr + n_value, x_scnlen); 648 1.1.1.2 christos break; 649 1.1.1.2 christos } 650 1.1.1.2 christos } 651 1.1.1.2 christos } 652 1.1.1.2 christos 653 1.1.1.2 christos if (symtab != NULL) 654 1.1.1.2 christos XDELETEVEC (symtab); 655 1.1 christos if (strtab != NULL) 656 1.1 christos XDELETEVEC (strtab); 657 1.1 christos XDELETEVEC (scnbuf); 658 1.1 christos 659 1.1 christos return NULL; 660 1.1 christos } 661 1.1 christos 662 1.1 christos /* Fetch the attributes for an simple_object_read. */ 663 1.1 christos 664 1.1 christos static void * 665 1.1 christos simple_object_xcoff_fetch_attributes (simple_object_read *sobj, 666 1.1 christos const char **errmsg ATTRIBUTE_UNUSED, 667 1.1 christos int *err ATTRIBUTE_UNUSED) 668 1.1 christos { 669 1.1 christos struct simple_object_xcoff_read *ocr = 670 1.1 christos (struct simple_object_xcoff_read *) sobj->data; 671 1.1 christos struct simple_object_xcoff_attributes *ret; 672 1.1 christos 673 1.1 christos ret = XNEW (struct simple_object_xcoff_attributes); 674 1.1 christos ret->magic = ocr->magic; 675 1.1 christos ret->flags = ocr->flags; 676 1.1 christos return ret; 677 1.1 christos } 678 1.1 christos 679 1.1 christos /* Release the private data for an simple_object_read. */ 680 1.1 christos 681 1.1 christos static void 682 1.1 christos simple_object_xcoff_release_read (void *data) 683 1.1 christos { 684 1.1 christos XDELETE (data); 685 1.1 christos } 686 1.1 christos 687 1.1 christos /* Compare two attributes structures. */ 688 1.1 christos 689 1.1 christos static const char * 690 1.1 christos simple_object_xcoff_attributes_merge (void *todata, void *fromdata, int *err) 691 1.1 christos { 692 1.1 christos struct simple_object_xcoff_attributes *to = 693 1.1 christos (struct simple_object_xcoff_attributes *) todata; 694 1.1 christos struct simple_object_xcoff_attributes *from = 695 1.1 christos (struct simple_object_xcoff_attributes *) fromdata; 696 1.1 christos 697 1.1 christos if (to->magic != from->magic) 698 1.1 christos { 699 1.1 christos *err = 0; 700 1.1 christos return "XCOFF object format mismatch"; 701 1.1 christos } 702 1.1 christos return NULL; 703 1.1 christos } 704 1.1 christos 705 1.1 christos /* Release the private data for an attributes structure. */ 706 1.1 christos 707 1.1 christos static void 708 1.1 christos simple_object_xcoff_release_attributes (void *data) 709 1.1 christos { 710 1.1 christos XDELETE (data); 711 1.1 christos } 712 1.1 christos 713 1.1 christos /* Prepare to write out a file. */ 714 1.1 christos 715 1.1 christos static void * 716 1.1 christos simple_object_xcoff_start_write (void *attributes_data, 717 1.1 christos const char **errmsg ATTRIBUTE_UNUSED, 718 1.1 christos int *err ATTRIBUTE_UNUSED) 719 1.1 christos { 720 1.1 christos struct simple_object_xcoff_attributes *attrs = 721 1.1 christos (struct simple_object_xcoff_attributes *) attributes_data; 722 1.1 christos struct simple_object_xcoff_attributes *ret; 723 1.1 christos 724 1.1 christos /* We're just going to record the attributes, but we need to make a 725 1.1 christos copy because the user may delete them. */ 726 1.1 christos ret = XNEW (struct simple_object_xcoff_attributes); 727 1.1 christos *ret = *attrs; 728 1.1 christos return ret; 729 1.1 christos } 730 1.1 christos 731 1.1 christos /* Write out a XCOFF filehdr. */ 732 1.1 christos 733 1.1 christos static int 734 1.1 christos simple_object_xcoff_write_filehdr (simple_object_write *sobj, int descriptor, 735 1.1 christos unsigned int nscns, size_t symtab_offset, 736 1.1 christos unsigned int nsyms, const char **errmsg, 737 1.1 christos int *err) 738 1.1 christos { 739 1.1 christos struct simple_object_xcoff_attributes *attrs = 740 1.1 christos (struct simple_object_xcoff_attributes *) sobj->data; 741 1.1 christos int u64 = attrs->magic == U64_TOCMAGIC; 742 1.1 christos unsigned char hdrbuf[sizeof (struct external_filehdr)]; 743 1.1 christos unsigned char *hdr; 744 1.1 christos void (*set_16) (unsigned char *, unsigned short); 745 1.1 christos void (*set_32) (unsigned char *, unsigned int); 746 1.1 christos void (*set_64) (unsigned char *, ulong_type); 747 1.1 christos 748 1.1 christos hdr = &hdrbuf[0]; 749 1.1 christos 750 1.1 christos set_16 = simple_object_set_big_16; 751 1.1 christos set_32 = simple_object_set_big_32; 752 1.1 christos set_64 = simple_object_set_big_64; 753 1.1 christos 754 1.1 christos memset (hdr, 0, sizeof (struct external_filehdr)); 755 1.1 christos 756 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic); 757 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns); 758 1.1 christos /* f_timdat left as zero. */ 759 1.1 christos if (u64) 760 1.1 christos { 761 1.1 christos set_64 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr), 762 1.1 christos symtab_offset); 763 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms), 764 1.1 christos nsyms); 765 1.1 christos /* f_opthdr left as zero. */ 766 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags), 767 1.1 christos attrs->flags); 768 1.1 christos } 769 1.1 christos else 770 1.1 christos { 771 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr), 772 1.1 christos symtab_offset); 773 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms), 774 1.1 christos nsyms); 775 1.1 christos /* f_opthdr left as zero. */ 776 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags), 777 1.1 christos attrs->flags); 778 1.1 christos } 779 1.1 christos 780 1.1 christos return simple_object_internal_write (descriptor, 0, hdrbuf, 781 1.1 christos sizeof (struct external_filehdr), 782 1.1 christos errmsg, err); 783 1.1 christos } 784 1.1 christos 785 1.1 christos /* Write out a XCOFF section header. */ 786 1.1 christos 787 1.1 christos static int 788 1.1 christos simple_object_xcoff_write_scnhdr (simple_object_write *sobj, 789 1.1 christos int descriptor, 790 1.1 christos const char *name, size_t *name_offset, 791 1.1 christos off_t scnhdr_offset, size_t scnsize, 792 1.1 christos off_t offset, unsigned int align, 793 1.1 christos const char **errmsg, int *err) 794 1.1 christos { 795 1.1 christos struct simple_object_xcoff_read *ocr = 796 1.1 christos (struct simple_object_xcoff_read *) sobj->data; 797 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC; 798 1.1 christos void (*set_32) (unsigned char *, unsigned int); 799 1.1 christos void (*set_64) (unsigned char *, unsigned int); 800 1.1 christos unsigned char hdrbuf[sizeof (struct external_scnhdr)]; 801 1.1 christos unsigned char *hdr; 802 1.1 christos size_t namelen; 803 1.1 christos unsigned int flags; 804 1.1 christos 805 1.1 christos set_32 = simple_object_set_big_32; 806 1.1 christos set_64 = simple_object_set_big_32; 807 1.1 christos 808 1.1 christos memset (hdrbuf, 0, sizeof hdrbuf); 809 1.1 christos hdr = &hdrbuf[0]; 810 1.1 christos 811 1.1 christos namelen = strlen (name); 812 1.1 christos if (namelen <= SCNNMLEN) 813 1.1 christos strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), 814 1.1 christos name, SCNNMLEN); 815 1.1 christos else 816 1.1 christos { 817 1.1 christos snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name), 818 1.1 christos SCNNMLEN, "/%lu", (unsigned long) *name_offset); 819 1.1 christos *name_offset += namelen + 1; 820 1.1 christos } 821 1.1 christos 822 1.1 christos /* s_paddr left as zero. */ 823 1.1 christos /* s_vaddr left as zero. */ 824 1.1 christos if (u64) 825 1.1 christos { 826 1.1 christos set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_size), 827 1.1 christos scnsize); 828 1.1 christos set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_scnptr), 829 1.1 christos offset); 830 1.1 christos } 831 1.1 christos else 832 1.1 christos { 833 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_size), 834 1.1 christos scnsize); 835 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_scnptr), 836 1.1 christos offset); 837 1.1 christos } 838 1.1 christos /* s_relptr left as zero. */ 839 1.1 christos /* s_lnnoptr left as zero. */ 840 1.1 christos /* s_nreloc left as zero. */ 841 1.1 christos /* s_nlnno left as zero. */ 842 1.1 christos flags = STYP_DATA; 843 1.1 christos if (align > 13) 844 1.1 christos align = 13; 845 1.1 christos if (u64) 846 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_flags), flags); 847 1.1 christos else 848 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_flags), flags); 849 1.1 christos 850 1.1 christos return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf, 851 1.1 christos u64 ? SCNHSZ64 : SCNHSZ32, 852 1.1 christos errmsg, err); 853 1.1 christos } 854 1.1 christos 855 1.1 christos /* Write out a complete XCOFF file. */ 856 1.1 christos 857 1.1 christos static const char * 858 1.1 christos simple_object_xcoff_write_to_file (simple_object_write *sobj, int descriptor, 859 1.1 christos int *err) 860 1.1 christos { 861 1.1 christos struct simple_object_xcoff_read *ocr = 862 1.1 christos (struct simple_object_xcoff_read *) sobj->data; 863 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC; 864 1.1 christos unsigned int nscns, secnum; 865 1.1 christos simple_object_write_section *section; 866 1.1 christos off_t scnhdr_offset; 867 1.1 christos size_t symtab_offset; 868 1.1 christos off_t secsym_offset; 869 1.1 christos unsigned int nsyms; 870 1.1 christos size_t offset; 871 1.1 christos size_t name_offset; 872 1.1 christos const char *errmsg; 873 1.1 christos unsigned char strsizebuf[4]; 874 1.1 christos /* The interface doesn't give us access to the name of the input file 875 1.1 christos yet. We want to use its basename for the FILE symbol. This is 876 1.1 christos what 'gas' uses when told to assemble from stdin. */ 877 1.1 christos const char *source_filename = "fake"; 878 1.1 christos size_t sflen; 879 1.1 christos union 880 1.1 christos { 881 1.1 christos struct external_syment sym; 882 1.1 christos union external_auxent aux; 883 1.1 christos } syms[2]; 884 1.1 christos void (*set_16) (unsigned char *, unsigned short); 885 1.1 christos void (*set_32) (unsigned char *, unsigned int); 886 1.1 christos 887 1.1 christos set_16 = simple_object_set_big_16; 888 1.1 christos set_32 = simple_object_set_big_32; 889 1.1 christos 890 1.1 christos nscns = 0; 891 1.1 christos for (section = sobj->sections; section != NULL; section = section->next) 892 1.1 christos ++nscns; 893 1.1 christos 894 1.1 christos scnhdr_offset = sizeof (struct external_filehdr) - (u64 ? 4 : 0); 895 1.1 christos offset = scnhdr_offset + nscns * (u64 ? SCNHSZ64 : SCNHSZ32); 896 1.1 christos name_offset = 4; 897 1.1 christos for (section = sobj->sections; section != NULL; section = section->next) 898 1.1 christos { 899 1.1 christos size_t mask; 900 1.1 christos size_t new_offset; 901 1.1 christos size_t scnsize; 902 1.1 christos struct simple_object_write_section_buffer *buffer; 903 1.1 christos 904 1.1 christos mask = (1U << section->align) - 1; 905 1.1 christos new_offset = offset & mask; 906 1.1 christos new_offset &= ~ mask; 907 1.1 christos while (new_offset > offset) 908 1.1 christos { 909 1.1 christos unsigned char zeroes[16]; 910 1.1 christos size_t write; 911 1.1 christos 912 1.1 christos memset (zeroes, 0, sizeof zeroes); 913 1.1 christos write = new_offset - offset; 914 1.1 christos if (write > sizeof zeroes) 915 1.1 christos write = sizeof zeroes; 916 1.1 christos if (!simple_object_internal_write (descriptor, offset, zeroes, write, 917 1.1 christos &errmsg, err)) 918 1.1 christos return errmsg; 919 1.1 christos } 920 1.1 christos 921 1.1 christos scnsize = 0; 922 1.1 christos for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) 923 1.1 christos { 924 1.1 christos if (!simple_object_internal_write (descriptor, offset + scnsize, 925 1.1 christos ((const unsigned char *) 926 1.1 christos buffer->buffer), 927 1.1 christos buffer->size, &errmsg, err)) 928 1.1 christos return errmsg; 929 1.1 christos scnsize += buffer->size; 930 1.1 christos } 931 1.1 christos 932 1.1 christos if (!simple_object_xcoff_write_scnhdr (sobj, descriptor, section->name, 933 1.1 christos &name_offset, scnhdr_offset, 934 1.1 christos scnsize, offset, section->align, 935 1.1 christos &errmsg, err)) 936 1.1 christos return errmsg; 937 1.1 christos 938 1.1 christos scnhdr_offset += u64 ? SCNHSZ64 : SCNHSZ32; 939 1.1 christos offset += scnsize; 940 1.1 christos } 941 1.1 christos 942 1.1 christos /* Symbol table is always half-word aligned. */ 943 1.1 christos offset += (offset & 1); 944 1.1 christos /* There is a file symbol and a section symbol per section, 945 1.1 christos and each of these has a single auxiliary symbol following. */ 946 1.1 christos nsyms = 2 * (nscns + 1); 947 1.1 christos symtab_offset = offset; 948 1.1 christos /* Advance across space reserved for symbol table to locate 949 1.1 christos start of string table. */ 950 1.1 christos offset += nsyms * SYMESZ; 951 1.1 christos 952 1.1 christos /* Write out file symbol. */ 953 1.1 christos memset (&syms[0], 0, sizeof (syms)); 954 1.1 christos if (!u64) 955 1.1 christos strcpy ((char *)&syms[0].sym.u.xcoff32.n.n_name[0], ".file"); 956 1.1 christos set_16 (&syms[0].sym.n_scnum[0], N_DEBUG); 957 1.1 christos set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE); 958 1.1 christos syms[0].sym.n_sclass[0] = C_FILE; 959 1.1 christos syms[0].sym.n_numaux[0] = 1; 960 1.1 christos /* The name need not be nul-terminated if it fits into the x_fname field 961 1.1 christos directly, but must be if it has to be placed into the string table. */ 962 1.1 christos sflen = strlen (source_filename); 963 1.1 christos if (sflen <= FILNMLEN) 964 1.1 christos memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen); 965 1.1 christos else 966 1.1 christos { 967 1.1 christos set_32 (&syms[1].aux.x_file._x.x_offset[0], name_offset); 968 1.1 christos if (!simple_object_internal_write (descriptor, offset + name_offset, 969 1.1 christos ((const unsigned char *) 970 1.1 christos source_filename), 971 1.1 christos sflen + 1, &errmsg, err)) 972 1.1 christos return errmsg; 973 1.1 christos name_offset += strlen (source_filename) + 1; 974 1.1 christos } 975 1.1 christos if (!simple_object_internal_write (descriptor, symtab_offset, 976 1.1 christos (const unsigned char *) &syms[0], 977 1.1 christos sizeof (syms), &errmsg, err)) 978 1.1 christos return errmsg; 979 1.1 christos 980 1.1 christos /* Write the string table length, followed by the strings and section 981 1.1 christos symbols in step with each other. */ 982 1.1 christos set_32 (strsizebuf, name_offset); 983 1.1 christos if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4, 984 1.1 christos &errmsg, err)) 985 1.1 christos return errmsg; 986 1.1 christos 987 1.1 christos name_offset = 4; 988 1.1 christos secsym_offset = symtab_offset + sizeof (syms); 989 1.1 christos memset (&syms[0], 0, sizeof (syms)); 990 1.1 christos set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE); 991 1.1 christos syms[0].sym.n_sclass[0] = C_STAT; 992 1.1 christos syms[0].sym.n_numaux[0] = 1; 993 1.1 christos secnum = 1; 994 1.1 christos 995 1.1 christos for (section = sobj->sections; section != NULL; section = section->next) 996 1.1 christos { 997 1.1 christos size_t namelen; 998 1.1 christos size_t scnsize; 999 1.1 christos struct simple_object_write_section_buffer *buffer; 1000 1.1 christos 1001 1.1 christos namelen = strlen (section->name); 1002 1.1 christos set_16 (&syms[0].sym.n_scnum[0], secnum++); 1003 1.1 christos scnsize = 0; 1004 1.1 christos for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) 1005 1.1 christos scnsize += buffer->size; 1006 1.1 christos set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize); 1007 1.1 christos if (namelen > SCNNMLEN) 1008 1.1 christos { 1009 1.1 christos set_32 (&syms[0].sym.u.xcoff32.n.n.n_zeroes[0], 0); 1010 1.1 christos set_32 (&syms[0].sym.u.xcoff32.n.n.n_offset[0], name_offset); 1011 1.1 christos if (!simple_object_internal_write (descriptor, offset + name_offset, 1012 1.1 christos ((const unsigned char *) 1013 1.1 christos section->name), 1014 1.1 christos namelen + 1, &errmsg, err)) 1015 1.1 christos return errmsg; 1016 1.1 christos name_offset += namelen + 1; 1017 1.1 christos } 1018 1.1 christos else 1019 1.1 christos { 1020 1.1 christos memcpy (&syms[0].sym.u.xcoff32.n.n_name[0], section->name, 1021 1.1 christos strlen (section->name)); 1022 1.1 christos memset (&syms[0].sym.u.xcoff32.n.n_name[strlen (section->name)], 0, 1023 1.1 christos N_SYMNMLEN - strlen (section->name)); 1024 1.1 christos } 1025 1.1 christos 1026 1.1 christos if (!simple_object_internal_write (descriptor, secsym_offset, 1027 1.1 christos (const unsigned char *) &syms[0], 1028 1.1 christos sizeof (syms), &errmsg, err)) 1029 1.1 christos return errmsg; 1030 1.1 christos secsym_offset += sizeof (syms); 1031 1.1 christos } 1032 1.1 christos 1033 1.1 christos if (!simple_object_xcoff_write_filehdr (sobj, descriptor, nscns, 1034 1.1 christos symtab_offset, nsyms, &errmsg, err)) 1035 1.1 christos return errmsg; 1036 1.1 christos 1037 1.1 christos return NULL; 1038 1.1 christos } 1039 1.1 christos 1040 1.1 christos /* Release the private data for an simple_object_write structure. */ 1041 1.1 christos 1042 1.1 christos static void 1043 1.1 christos simple_object_xcoff_release_write (void *data) 1044 1.1 christos { 1045 1.1 christos XDELETE (data); 1046 1.1 christos } 1047 1.1 christos 1048 1.1 christos /* The XCOFF functions. */ 1049 1.1 christos 1050 1.1 christos const struct simple_object_functions simple_object_xcoff_functions = 1051 1.1 christos { 1052 1.1 christos simple_object_xcoff_match, 1053 1.1 christos simple_object_xcoff_find_sections, 1054 1.1 christos simple_object_xcoff_fetch_attributes, 1055 1.1 christos simple_object_xcoff_release_read, 1056 1.1 christos simple_object_xcoff_attributes_merge, 1057 1.1 christos simple_object_xcoff_release_attributes, 1058 1.1 christos simple_object_xcoff_start_write, 1059 1.1 christos simple_object_xcoff_write_to_file, 1060 1.1.1.2 christos simple_object_xcoff_release_write, 1061 1.1.1.2 christos NULL 1062 1.1 christos }; 1063