1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <string.h> 27 #include <stdio.h> 28 #include <sys/types.h> 29 #include <sgs.h> 30 #include <debug.h> 31 #include <_libld.h> 32 #include <dwarf.h> 33 #include <stdlib.h> 34 35 /* 36 * A EH_FRAME_HDR consists of the following: 37 * 38 * Encoding Field 39 * -------------------------------- 40 * unsigned byte version 41 * unsigned byte eh_frame_ptr_enc 42 * unsigned byte fde_count_enc 43 * unsigned byte table_enc 44 * encoded eh_frame_ptr 45 * encoded fde_count 46 * [ binary search table ] 47 * 48 * The binary search table entries each consists of: 49 * 50 * encoded initial_func_loc 51 * encoded FDE_address 52 * 53 * The entries in the binary search table are sorted 54 * in a increasing order by the initial location. 55 * 56 * 57 * version 58 * 59 * Version of the .eh_frame_hdr format. This value shall be 1. 60 * 61 * eh_frame_ptr_enc 62 * 63 * The encoding format of the eh_frame_ptr field. For shared 64 * libraries the encoding must be 65 * DW_EH_PE_sdata4|DW_EH_PE_pcrel or 66 * DW_EH_PE_sdata4|DW_EH_PE_datarel. 67 * 68 * 69 * fde_count_enc 70 * 71 * The encoding format of the fde_count field. A value of 72 * DW_EH_PE_omit indicates the binary search table is not 73 * present. 74 * 75 * table_enc 76 * 77 * The encoding format of the entries in the binary search 78 * table. A value of DW_EH_PE_omit indicates the binary search 79 * table is not present. For shared libraries the encoding 80 * must be DW_EH_PE_sdata4|DW_EH_PE_pcrel or 81 * DW_EH_PE_sdata4|DW_EH_PE_datarel. 82 * 83 * 84 * eh_frame_ptr 85 * 86 * The encoded value of the pointer to the start of the 87 * .eh_frame section. 88 * 89 * fde_count 90 * 91 * The encoded value of the count of entries in the binary 92 * search table. 93 * 94 * binary search table 95 * 96 * A binary search table containing fde_count entries. Each 97 * entry of the table consist of two encoded values, the 98 * initial location of the function to which an FDE applies, 99 * and the address of the FDE. The entries are sorted in an 100 * increasing order by the initial location value. 101 * 102 */ 103 104 105 /* 106 * EH_FRAME sections 107 * ================= 108 * 109 * The call frame information needed for unwinding the stack is output in 110 * an ELF section(s) of type SHT_AMD64_UNWIND (amd64) or SHT_PROGBITS (other). 111 * In the simplest case there will be one such section per object file and it 112 * will be named ".eh_frame". An .eh_frame section consists of one or more 113 * subsections. Each subsection contains a CIE (Common Information Entry) 114 * followed by varying number of FDEs (Frame Descriptor Entry). A FDE 115 * corresponds to an explicit or compiler generated function in a 116 * compilation unit, all FDEs can access the CIE that begins their 117 * subsection for data. 118 * 119 * If an object file contains C++ template instantiations, there shall be 120 * a separate CIE immediately preceding each FDE corresponding to an 121 * instantiation. 122 * 123 * Using the preferred encoding specified below, the .eh_frame section can 124 * be entirely resolved at link time and thus can become part of the 125 * text segment. 126 * 127 * .eh_frame Section Layout 128 * ------------------------ 129 * 130 * EH_PE encoding below refers to the pointer encoding as specified in the 131 * enhanced LSB Chapter 7 for Eh_Frame_Hdr. 132 * 133 * Common Information Entry (CIE) 134 * ------------------------------ 135 * CIE has the following format: 136 * 137 * Length 138 * in 139 * Field Byte Description 140 * ----- ------ ----------- 141 * 1. Length 4 Length of CIE (not including 142 * this 4-byte field). 143 * 144 * 2. CIE id 4 Value Zero (0) for .eh_frame 145 * (used to distinguish CIEs and 146 * FDEs when scanning the section) 147 * 148 * 3. Version 1 Value One (1) 149 * 150 * 4. CIE Augmentation string Null-terminated string with legal 151 * values being "" or 'z' optionally 152 * followed by single occurrences of 153 * 'P', 'L', or 'R' in any order. 154 * String The presence of character(s) in the 155 * string dictates the content of 156 * field 8, the Augmentation Section. 157 * Each character has one or two 158 * associated operands in the AS. 159 * Operand order depends on 160 * position in the string ('z' must 161 * be first). 162 * 163 * 5. Code Align Factor uleb128 To be multiplied with the 164 * "Advance Location" instructions in 165 * the Call Frame Instructions 166 * 167 * 6. Data Align Factor sleb128 To be multiplied with all offset 168 * in the Call Frame Instructions 169 * 170 * 7. Ret Address Reg 1 A "virtual" register representation 171 * of the return address. In Dwarf V2, 172 * this is a byte, otherwise it is 173 * uleb128. It is a byte in gcc 3.3.x 174 * 175 * 8. Optional CIE varying Present if Augmentation String in 176 * Augmentation Section field 4 is not 0. 177 * 178 * z: 179 * size uleb128 Length of the remainder of the 180 * Augmentation Section 181 * 182 * P: 183 * personality_enc 1 Encoding specifier - preferred 184 * value is a pc-relative, signed 185 * 4-byte 186 * 187 * 188 * personality routine (encoded) Encoded pointer to personality 189 * routine (actually to the PLT 190 * entry for the personality 191 * routine) 192 * R: 193 * code_enc 1 Non-default encoding for the 194 * code-pointers (FDE members 195 * "initial_location" and "address_range" 196 * and the operand for DW_CFA_set_loc) 197 * - preferred value is pc-relative, 198 * signed 4-byte. 199 * L: 200 * lsda_enc 1 FDE augmentation bodies may contain 201 * LSDA pointers. If so they are 202 * encoded as specified here - 203 * preferred value is pc-relative, 204 * signed 4-byte possibly indirect 205 * thru a GOT entry. 206 * 207 * 208 * 9. Optional Call Frame varying 209 * Instructions 210 * 211 * The size of the optional call frame instruction area must be computed 212 * based on the overall size and the offset reached while scanning the 213 * preceding fields of the CIE. 214 * 215 * 216 * Frame Descriptor Entry (FDE) 217 * ---------------------------- 218 * FDE has the following format: 219 * 220 * Length 221 * in 222 * Field Byte Description 223 * ----- ------ ----------- 224 * 1. Length 4 Length of remainder of this FDE 225 * 226 * 2. CIE Pointer 4 Distance from this field to the 227 * nearest preceding CIE 228 * (uthe value is subtracted from the 229 * current address). This value 230 * can never be zero and thus can 231 * be used to distinguish CIE's and 232 * FDE's when scanning the 233 * .eh_frame section 234 * 235 * 3. Initial Location varying Reference to the function code 236 * corresponding to this FDE. 237 * If 'R' is missing from the CIE 238 * Augmentation String, the field is an 239 * 8-byte absolute pointer. Otherwise, 240 * the corresponding EH_PE encoding in the 241 * CIE Augmentation Section is used to 242 * interpret the reference. 243 * 244 * 4. Address Range varying Size of the function code corresponding 245 * to this FDE. 246 * If 'R' is missing from the CIE 247 * Augmentation String, the field is an 248 * 8-byte unsigned number. Otherwise, 249 * the size is determined by the 250 * corresponding EH_PE encoding in the 251 * CIE Augmentation Section (the 252 * value is always absolute). 253 * 254 * 5. Optional FDE varying present if CIE augmentation 255 * Augmentation Section string is non-empty. 256 * 257 * 258 * 'z': 259 * length uleb128 length of the remainder of the 260 * FDE augmentation section 261 * 262 * 263 * 'L' (and length > 0): 264 * LSDA varying LSDA pointer, encoded in the 265 * format specified by the 266 * corresponding operand in the CIE's 267 * augmentation body. 268 * 269 * 6. Optional Call varying 270 * Frame Instructions 271 * 272 * The size of the optional call frame instruction area must be computed 273 * based on the overall size and the offset reached while scanning the 274 * preceding fields of the FDE. 275 * 276 * The overall size of a .eh_frame section is given in the ELF section 277 * header. The only way to determine the number of entries is to scan 278 * the section till the end and count. 279 * 280 */ 281 282 283 284 285 static uint_t 286 extract_uint(const uchar_t *data, uint64_t *ndx, int do_swap) 287 { 288 uint_t r; 289 uchar_t *p = (uchar_t *)&r; 290 291 data += *ndx; 292 if (do_swap) 293 UL_ASSIGN_BSWAP_WORD(p, data); 294 else 295 UL_ASSIGN_WORD(p, data); 296 297 (*ndx) += 4; 298 return (r); 299 } 300 301 /* 302 * Create an unwind header (.eh_frame_hdr) output section. 303 * The section is created and space reserved, but the data 304 * is not copied into place. That is done by a later call 305 * to ld_unwind_populate(), after active relocations have been 306 * processed. 307 * 308 * When GNU linkonce processing is in effect, we can end up in a situation 309 * where the FDEs related to discarded sections remain in the eh_frame 310 * section. Ideally, we would remove these dead entries from eh_frame. 311 * However, that optimization has not yet been implemented. In the current 312 * implementation, the number of dead FDEs cannot be determined until 313 * active relocations are processed, and that processing follows the 314 * call to this function. This means that we are unable to detect dead FDEs 315 * here, and the section created by this routine is sized for maximum case 316 * where all FDEs are valid. 317 */ 318 uintptr_t 319 ld_unwind_make_hdr(Ofl_desc *ofl) 320 { 321 int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0; 322 Shdr *shdr; 323 Elf_Data *elfdata; 324 Is_desc *isp; 325 size_t size; 326 Xword fde_cnt; 327 Aliste idx1; 328 Os_desc *osp; 329 330 /* 331 * we only build a unwind header if we have 332 * some unwind information in the file. 333 */ 334 if (ofl->ofl_unwind == NULL) 335 return (1); 336 337 /* 338 * Allocate and initialize the Elf_Data structure. 339 */ 340 if ((elfdata = libld_calloc(sizeof (Elf_Data), 1)) == NULL) 341 return (S_ERROR); 342 elfdata->d_type = ELF_T_BYTE; 343 elfdata->d_align = ld_targ.t_m.m_word_align; 344 elfdata->d_version = ofl->ofl_dehdr->e_version; 345 346 /* 347 * Allocate and initialize the Shdr structure. 348 */ 349 if ((shdr = libld_calloc(sizeof (Shdr), 1)) == NULL) 350 return (S_ERROR); 351 shdr->sh_type = ld_targ.t_m.m_sht_unwind; 352 shdr->sh_flags = SHF_ALLOC; 353 shdr->sh_addralign = ld_targ.t_m.m_word_align; 354 shdr->sh_entsize = 0; 355 356 /* 357 * Allocate and initialize the Is_desc structure. 358 */ 359 if ((isp = libld_calloc(1, sizeof (Is_desc))) == NULL) 360 return (S_ERROR); 361 isp->is_name = MSG_ORIG(MSG_SCN_UNWINDHDR); 362 isp->is_shdr = shdr; 363 isp->is_indata = elfdata; 364 365 if ((ofl->ofl_unwindhdr = ld_place_section(ofl, isp, NULL, 366 ld_targ.t_id.id_unwindhdr, NULL)) == (Os_desc *)S_ERROR) 367 return (S_ERROR); 368 369 /* 370 * Scan through all of the input Frame information, counting each FDE 371 * that requires an index. Each fde_entry gets a corresponding entry 372 * in the binary search table. 373 */ 374 fde_cnt = 0; 375 for (APLIST_TRAVERSE(ofl->ofl_unwind, idx1, osp)) { 376 Aliste idx2; 377 int os_isdescs_idx; 378 379 OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx2, isp) { 380 uchar_t *data; 381 uint64_t off = 0; 382 383 data = isp->is_indata->d_buf; 384 size = isp->is_indata->d_size; 385 386 while (off < size) { 387 uint_t length, id; 388 uint64_t ndx = 0; 389 390 /* 391 * Extract length in lsb format. A zero length 392 * indicates that this CIE is a terminator and 393 * that processing for unwind information is 394 * complete. 395 */ 396 length = extract_uint(data + off, &ndx, bswap); 397 if (length == 0) 398 break; 399 400 /* 401 * Extract CIE id in lsb format. 402 */ 403 id = extract_uint(data + off, &ndx, bswap); 404 405 /* 406 * A CIE record has a id of '0', otherwise 407 * this is a FDE entry and the 'id' is the 408 * CIE pointer. 409 */ 410 if (id == 0) { 411 uint_t cieversion; 412 /* 413 * The only CIE version supported 414 * is '1' - quick sanity check 415 * here. 416 */ 417 cieversion = data[off + ndx]; 418 ndx += 1; 419 /* BEGIN CSTYLED */ 420 if (cieversion != 1) { 421 ld_eprintf(ofl, ERR_FATAL, 422 MSG_INTL(MSG_UNW_BADCIEVERS), 423 isp->is_file->ifl_name, 424 isp->is_name, off); 425 return (S_ERROR); 426 } 427 /* END CSTYLED */ 428 } else { 429 fde_cnt++; 430 } 431 off += length + 4; 432 } 433 } 434 } 435 436 /* 437 * section size: 438 * byte version +1 439 * byte eh_frame_ptr_enc +1 440 * byte fde_count_enc +1 441 * byte table_enc +1 442 * 4 bytes eh_frame_ptr +4 443 * 4 bytes fde_count +4 444 * [4 bytes] [4bytes] * fde_count ... 445 */ 446 size = 12 + (8 * fde_cnt); 447 448 if ((elfdata->d_buf = libld_calloc(size, 1)) == NULL) 449 return (S_ERROR); 450 elfdata->d_size = size; 451 shdr->sh_size = (Xword)size; 452 453 return (1); 454 } 455 456 /* 457 * the comparator function needs to calculate 458 * the actual 'initloc' of a bintab entry - to 459 * do this we initialize the following global to point 460 * to it. 461 */ 462 static Addr framehdr_addr; 463 464 static int 465 bintabcompare(const void *p1, const void *p2) 466 { 467 uint_t *bintab1, *bintab2; 468 uint_t ent1, ent2; 469 470 bintab1 = (uint_t *)p1; 471 bintab2 = (uint_t *)p2; 472 473 assert(bintab1 != 0); 474 assert(bintab2 != 0); 475 476 ent1 = *bintab1 + framehdr_addr; 477 ent2 = *bintab2 + framehdr_addr; 478 479 if (ent1 > ent2) 480 return (1); 481 if (ent1 < ent2) 482 return (-1); 483 return (0); 484 } 485 486 uintptr_t 487 ld_unwind_populate_hdr(Ofl_desc *ofl) 488 { 489 uchar_t *hdrdata; 490 uint_t *binarytable; 491 uint_t hdroff; 492 Aliste idx; 493 Addr hdraddr; 494 Os_desc *hdrosp; 495 Os_desc *osp; 496 Os_desc *first_unwind; 497 uint_t fde_count; 498 uint_t *uint_ptr; 499 int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0; 500 501 /* 502 * Are we building the unwind hdr? 503 */ 504 if ((hdrosp = ofl->ofl_unwindhdr) == 0) 505 return (1); 506 507 hdrdata = hdrosp->os_outdata->d_buf; 508 hdraddr = hdrosp->os_shdr->sh_addr; 509 hdroff = 0; 510 511 /* 512 * version == 1 513 */ 514 hdrdata[hdroff++] = 1; 515 /* 516 * The encodings are: 517 * 518 * eh_frameptr_enc sdata4 | pcrel 519 * fde_count_enc udata4 520 * table_enc sdata4 | datarel 521 */ 522 hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; 523 hdrdata[hdroff++] = DW_EH_PE_udata4; 524 hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_datarel; 525 526 /* 527 * Header Offsets 528 * ----------------------------------- 529 * byte version +1 530 * byte eh_frame_ptr_enc +1 531 * byte fde_count_enc +1 532 * byte table_enc +1 533 * 4 bytes eh_frame_ptr +4 534 * 4 bytes fde_count +4 535 */ 536 /* LINTED */ 537 binarytable = (uint_t *)(hdrdata + 12); 538 first_unwind = 0; 539 fde_count = 0; 540 541 for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) { 542 uchar_t *data; 543 size_t size; 544 uint64_t off = 0; 545 uint_t cieRflag = 0, ciePflag = 0; 546 Shdr *shdr; 547 548 /* 549 * remember first UNWIND section to 550 * point to in the frame_ptr entry. 551 */ 552 if (first_unwind == 0) 553 first_unwind = osp; 554 555 data = osp->os_outdata->d_buf; 556 shdr = osp->os_shdr; 557 size = shdr->sh_size; 558 559 while (off < size) { 560 uint_t length, id; 561 uint64_t ndx = 0; 562 563 /* 564 * Extract length in lsb format. A zero length 565 * indicates that this CIE is a terminator and that 566 * processing of unwind information is complete. 567 */ 568 length = extract_uint(data + off, &ndx, bswap); 569 if (length == 0) 570 goto done; 571 572 /* 573 * Extract CIE id in lsb format. 574 */ 575 id = extract_uint(data + off, &ndx, bswap); 576 577 /* 578 * A CIE record has a id of '0'; otherwise 579 * this is a FDE entry and the 'id' is the 580 * CIE pointer. 581 */ 582 if (id == 0) { 583 char *cieaugstr; 584 uint_t cieaugndx; 585 586 ciePflag = 0; 587 cieRflag = 0; 588 /* 589 * We need to drill through the CIE 590 * to find the Rflag. It's the Rflag 591 * which describes how the FDE code-pointers 592 * are encoded. 593 */ 594 595 /* 596 * burn through version 597 */ 598 ndx++; 599 600 /* 601 * augstr 602 */ 603 cieaugstr = (char *)(&data[off + ndx]); 604 ndx += strlen(cieaugstr) + 1; 605 606 /* 607 * calign & dalign 608 */ 609 (void) uleb_extract(&data[off], &ndx); 610 (void) sleb_extract(&data[off], &ndx); 611 612 /* 613 * retreg 614 */ 615 ndx++; 616 617 /* 618 * we walk through the augmentation 619 * section now looking for the Rflag 620 */ 621 for (cieaugndx = 0; cieaugstr[cieaugndx]; 622 cieaugndx++) { 623 /* BEGIN CSTYLED */ 624 switch (cieaugstr[cieaugndx]) { 625 case 'z': 626 /* size */ 627 (void) uleb_extract(&data[off], 628 &ndx); 629 break; 630 case 'P': 631 /* personality */ 632 ciePflag = data[off + ndx]; 633 ndx++; 634 /* 635 * Just need to extract the 636 * value to move on to the next 637 * field. 638 */ 639 (void) dwarf_ehe_extract( 640 &data[off + ndx], 641 &ndx, ciePflag, 642 ofl->ofl_dehdr->e_ident, 643 shdr->sh_addr, off + ndx); 644 break; 645 case 'R': 646 /* code encoding */ 647 cieRflag = data[off + ndx]; 648 ndx++; 649 break; 650 case 'L': 651 /* lsda encoding */ 652 ndx++; 653 break; 654 } 655 /* END CSTYLED */ 656 } 657 } else { 658 uint_t bintabndx; 659 uint64_t initloc; 660 uint64_t fdeaddr; 661 662 initloc = dwarf_ehe_extract(&data[off], 663 &ndx, cieRflag, ofl->ofl_dehdr->e_ident, 664 shdr->sh_addr, off + ndx); 665 666 /* 667 * Ignore FDEs with initloc set to 0. 668 * initloc will not be 0 unless this FDE was 669 * abandoned due to GNU linkonce processing. 670 * The 0 value occurs because we don't resolve 671 * sloppy relocations for unwind header target 672 * sections. 673 */ 674 if (initloc != 0) { 675 bintabndx = fde_count * 2; 676 fde_count++; 677 678 /* 679 * FDEaddr is adjusted 680 * to account for the length & id which 681 * have already been consumed. 682 */ 683 fdeaddr = shdr->sh_addr + off; 684 685 binarytable[bintabndx] = 686 (uint_t)(initloc - hdraddr); 687 binarytable[bintabndx + 1] = 688 (uint_t)(fdeaddr - hdraddr); 689 } 690 } 691 692 /* 693 * the length does not include the length 694 * itself - so account for that too. 695 */ 696 off += length + 4; 697 } 698 } 699 700 done: 701 /* 702 * Do a quicksort on the binary table. If this is a cross 703 * link from a system with the opposite byte order, xlate 704 * the resulting values into LSB order. 705 */ 706 framehdr_addr = hdraddr; 707 qsort((void *)binarytable, (size_t)fde_count, 708 (size_t)(sizeof (uint_t) * 2), bintabcompare); 709 if (bswap) { 710 uint_t *btable = binarytable; 711 uint_t cnt; 712 713 for (cnt = fde_count * 2; cnt-- > 0; btable++) 714 *btable = ld_bswap_Word(*btable); 715 } 716 717 /* 718 * Fill in: 719 * first_frame_ptr 720 * fde_count 721 */ 722 hdroff = 4; 723 /* LINTED */ 724 uint_ptr = (uint_t *)(&hdrdata[hdroff]); 725 *uint_ptr = first_unwind->os_shdr->sh_addr - 726 (hdrosp->os_shdr->sh_addr + hdroff); 727 if (bswap) 728 *uint_ptr = ld_bswap_Word(*uint_ptr); 729 730 hdroff += 4; 731 /* LINTED */ 732 uint_ptr = (uint_t *)&hdrdata[hdroff]; 733 *uint_ptr = fde_count; 734 if (bswap) 735 *uint_ptr = ld_bswap_Word(*uint_ptr); 736 737 /* 738 * If relaxed relocations are active, then there is a chance 739 * that we didn't use all the space reserved for this section. 740 * For details, see the note at head of ld_unwind_make_hdr() above. 741 * 742 * Find the PT_SUNW_UNWIND program header, and change the size values 743 * to the size of the subset of the section that was actually used. 744 */ 745 if (ofl->ofl_flags1 & FLG_OF1_RLXREL) { 746 Word phnum = ofl->ofl_nehdr->e_phnum; 747 Phdr *phdr = ofl->ofl_phdr; 748 749 for (; phnum-- > 0; phdr++) { 750 if (phdr->p_type == PT_SUNW_UNWIND) { 751 phdr->p_memsz = 12 + (8 * fde_count); 752 phdr->p_filesz = phdr->p_memsz; 753 break; 754 } 755 } 756 } 757 758 return (1); 759 } 760 761 /* 762 * Append an .eh_frame section to our output list if not already present. 763 * 764 * Usually, there is a single .eh_frame output section. However, there can 765 * be more if there are incompatible section flags on incoming sections. 766 * If this does happen, the frame_ptr field of the eh_frame_hdr section 767 * will point at the base of the first output section, and the other 768 * sections will not be accessible via frame_ptr. However, the .eh_frame_hdr 769 * will be able to access all the data in the different .eh_frame sections, 770 * because the entries in sorted table are all encoded as DW_EH_PE_datarel. 771 */ 772 uintptr_t 773 ld_unwind_register(Os_desc *osp, Ofl_desc * ofl) 774 { 775 Aliste idx; 776 Os_desc *_osp; 777 /* 778 * Check to see if this output section is already 779 * on the list. 780 */ 781 for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, _osp)) 782 if (osp == _osp) 783 return (1); 784 785 /* 786 * Append output section to unwind list 787 */ 788 if (aplist_append(&ofl->ofl_unwind, osp, AL_CNT_OFL_UNWIND) == NULL) 789 return (S_ERROR); 790 791 return (1); 792 } 793