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