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 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1988 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30#pragma ident	"@(#)clscook.c	1.11	08/05/31 SMI"
31
32/*
33 * This stuff used to live in cook.c, but was moved out to
34 * facilitate dual (Elf32 and Elf64) compilation.  See block
35 * comment in cook.c for more info.
36 */
37
38#include <string.h>
39#include <ar.h>
40#include <stdlib.h>
41#include <errno.h>
42#include "decl.h"
43#include "member.h"
44#include "msg.h"
45
46#if defined(__APPLE__)
47#include <mach-o/fat.h>
48#include <mach-o/loader.h>
49#include <mach-o/nlist.h>
50#include <mach-o/stab.h>
51#include <sys/mman.h>
52
53static struct xSectName
54{
55	const char *MachoName;
56	const char *PrimaryElfName;
57	const char *SecondaryElfName;
58}
59xTab[] =
60{
61	{SECT_TEXT, ".text", "non-SEG_TEXT .text" },
62	{SECT_DATA, ".data", "non-SEG_DATA .data" },
63	{SECT_BSS, ".bss", "non-SEG_DATA .bss" },
64	{SECT_CTF, ".SUNW_ctf", 0},
65	{"__symbol_table", ".symtab", 0 },
66	{"__debug_info", ".debug_info", 0 },
67	{"__debug_abbrev", ".debug_abbrev", 0 },
68	{"__debug_aranges", ".debug_aranges", 0 },
69	{"__debug_ranges", ".debug_ranges", 0 },
70	{"__debug_line", ".debug_line", 0 },
71	{"__debug_frame", ".debug_frame", 0  },
72	{"__debug_loc", ".debug_loc", 0  },
73	{"__debug_pubnames", ".debug_pubnames", 0  },
74	{"__debug_str", ".debug_str", 0  },
75	{"__debug_funcnames", ".debug_funcnames", 0  },
76	{"__debug_typenames", ".debug_typenames", 0  },
77	{"__debug_pubtypes", ".debug_pubtypes", 0  },
78	{"__debug_varnames", ".debug_varnames", 0  },
79	{"__debug_weaknames", ".debug_weaknames", 0  },
80	{"__debug_macinfo", ".debug_macinfo", 0  },
81	{"__eh_frame", ".eh_frame", 0 },
82	{"__dir_str_table", ".dir_str_table", 0 } /* Directly addressed Mach-o string table. */
83};
84#define SIZE_XTAB (sizeof(xTab)/sizeof(xTab[0]))
85#define	LOADER_H_NAME_LENGTH 16
86
87static
88int elf_macho_str_cookie(const char *name, int primary)
89{
90	int j;
91	int ret = SIZE_XTAB << 1;
92
93	for (j = 0; j < SIZE_XTAB && name; j++) {
94		if (0 == strncmp(name, xTab[j].MachoName, LOADER_H_NAME_LENGTH)) {
95			if (!primary && xTab[j].SecondaryElfName)
96				ret = (j << 1) + 1;
97			else
98				ret = j << 1;
99			break;
100		}
101	}
102
103	return ret;
104}
105
106#if	defined(_ELF64) /* Want just one definition, so compile only under -D_ELF64 */
107const char *elf_macho_str_off(size_t off)
108{
109	if (off >= (SIZE_XTAB << 1))
110		return ".unknown mach-o";
111	else if (off & 1)
112		return xTab[off>>1].SecondaryElfName;
113	else
114		return xTab[off>>1].PrimaryElfName;
115}
116#endif
117
118static
119Elf32_Word STTSect(const char *sectname)
120{
121	if (0 == strcmp(sectname, SECT_TEXT))
122		return STT_FUNC;
123	else if (0 == strcmp(sectname, SECT_DATA))
124		return STT_OBJECT;
125	else if (0 == strcmp(sectname, SECT_BSS))
126		return STT_OBJECT;
127	else
128		return STT_OBJECT;
129}
130#endif /* __APPLE__ */
131
132/*
133 * This module is compiled twice, the second time having
134 * -D_ELF64 defined.  The following set of macros, along
135 * with machelf.h, represent the differences between the
136 * two compilations.  Be careful *not* to add any class-
137 * dependent code (anything that has elf32 or elf64 in the
138 * name) to this code without hiding it behind a switch-
139 * able macro like these.
140 */
141#if	defined(_ELF64)
142#define	Snode		Snode64
143#define	ELFCLASS	ELFCLASS64
144#define	ElfField	Elf64
145#define	_elf_snode_init	_elf64_snode_init
146#define	_elf_prepscan	_elf64_prepscan
147#define	_elf_cookscn	_elf64_cookscn
148#define	_elf_mtype	_elf64_mtype
149#define	_elf_msize	_elf64_msize
150#define	elf_fsize	elf64_fsize
151#define	_elf_snode	_elf64_snode
152#define	_elf_ehdr	_elf64_ehdr
153#define	elf_xlatetom	elf64_xlatetom
154#define	_elf_phdr	_elf64_phdr
155#define	_elf_shdr	_elf64_shdr
156#define	_elf_prepscn	_elf64_prepscn
157
158#if defined(__APPLE__)
159#define _mach_header	mach_header_64
160#define _MH_CIGAM	MH_CIGAM_64
161#define _swap_mh	__swap_mach_header_64
162#define _elf_word	Elf64_Word
163#define _elf_addr	Elf64_Addr
164#define _elf_off	Elf64_Off
165#define _SHN_MACHO	SHN_MACHO_64
166#define _nlist		nlist_64
167#define _addralign	8
168#define _SWAPVAL	SWAP64
169
170#define _LC_SEGMENT	LC_SEGMENT_64
171#define _segcmd		segment_command_64
172#define _sect		section_64
173#define _swapsegcmd	__swap_segment_command_64
174#define _swapsect	__swap_section_64
175
176#endif /* __APPLE__ */
177
178#else  /* Elf32 */
179#define	Snode		Snode32
180#define	ELFCLASS	ELFCLASS32
181#define	ElfField	Elf32
182#define	_elf_snode_init	_elf32_snode_init
183#define	_elf_prepscan	_elf32_prepscan
184#define	_elf_cookscn	_elf32_cookscn
185#define	_elf_mtype	_elf32_mtype
186#define	_elf_msize	_elf32_msize
187#define	elf_fsize	elf32_fsize
188#define	_elf_snode	_elf32_snode
189#define	_elf_ehdr	_elf32_ehdr
190#define	elf_xlatetom	elf32_xlatetom
191#define	_elf_phdr	_elf32_phdr
192#define	_elf_shdr	_elf32_shdr
193#define	_elf_prepscn	_elf32_prepscn
194
195#if defined(__APPLE__)
196#define _mach_header	mach_header
197#define _MH_CIGAM	MH_CIGAM
198#define _swap_mh	__swap_mach_header
199#define _elf_word	Elf32_Word
200#define _elf_addr	Elf32_Addr
201#define _elf_off	Elf32_Off
202#define _SHN_MACHO	SHN_MACHO
203#define _nlist		nlist
204#define _addralign	4
205#define _SWAPVAL	SWAP32
206
207#define _LC_SEGMENT	LC_SEGMENT
208#define _segcmd		segment_command
209#define _sect		section
210#define _swapsegcmd	__swap_segment_command
211#define _swapsect	__swap_section
212
213#endif /* __APPLE__ */
214
215#endif /* _ELF64 */
216
217
218static Okay
219_elf_prepscn(Elf *elf, size_t cnt)
220{
221	NOTE(ASSUMING_PROTECTED(*elf))
222	Elf_Scn *	s;
223	Elf_Scn *	end;
224
225	if (cnt == 0)
226		return (OK_YES);
227
228	if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) {
229		_elf_seterr(EMEM_SCN, errno);
230		return (OK_NO);
231	}
232	NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
233	elf->ed_scntabsz = cnt;
234	end = s + cnt;
235	elf->ed_hdscn = s;
236	do {
237		*s = _elf_snode_init.sb_scn;
238		s->s_elf = elf;
239		s->s_next = s + 1;
240		s->s_index = s - elf->ed_hdscn;
241		s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index;
242		ELFMUTEXINIT(&s->s_mutex);
243
244		/*
245		 * Section has not yet been cooked!
246		 *
247		 * We don't cook a section until it's data is actually
248		 * referenced.
249		 */
250		s->s_myflags = 0;
251	} while (++s < end);
252
253	elf->ed_tlscn = --s;
254	s->s_next = 0;
255
256	/*
257	 * Section index SHN_UNDEF (0) does not and cannot
258	 * have a data buffer.  Fix it here.  Also mark the
259	 * initial section as being allocated for the block
260	 */
261
262	s = elf->ed_hdscn;
263	s->s_myflags = SF_ALLOC;
264	s->s_hdnode = 0;
265	s->s_tlnode = 0;
266	NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
267	return (OK_YES);
268}
269
270
271Okay
272_elf_cookscn(Elf_Scn * s)
273{
274	NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf)))
275	Elf *			elf;
276	Shdr *			sh;
277	register Dnode *	d = &s->s_dnode;
278	size_t			fsz, msz;
279	unsigned		work;
280
281	NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d))
282	s->s_hdnode = s->s_tlnode = d;
283	s->s_err = 0;
284	s->s_shflags = 0;
285	s->s_uflags = 0;
286
287
288	/*
289	 * Prepare d_data for inspection, but don't actually
290	 * translate data until needed.  Leave the READY
291	 * flag off.  NOBITS sections see zero size.
292	 */
293	elf = s->s_elf;
294	sh = s->s_shdr;
295
296	d->db_scn = s;
297	d->db_off = sh->sh_offset;
298	d->db_data.d_align = sh->sh_addralign;
299	d->db_data.d_version = elf->ed_version;
300	ELFACCESSDATA(work, _elf_work)
301	d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work);
302	d->db_data.d_buf = 0;
303	d->db_data.d_off = 0;
304	fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version);
305	msz = _elf_msize(d->db_data.d_type, elf->ed_version);
306	d->db_data.d_size = (sh->sh_size / fsz) * msz;
307	d->db_shsz = sh->sh_size;
308	d->db_raw = 0;
309	d->db_buf = 0;
310	d->db_uflags = 0;
311	d->db_myflags = 0;
312	d->db_next = 0;
313
314	if (sh->sh_type != SHT_NOBITS)
315		d->db_fsz = sh->sh_size;
316	else
317		d->db_fsz = 0;
318
319	s->s_myflags |= SF_READY;
320
321	NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d))
322	return (OK_YES);
323}
324
325
326
327Snode *
328_elf_snode()
329{
330	register Snode	*s;
331
332	if ((s = malloc(sizeof (Snode))) == 0) {
333		_elf_seterr(EMEM_SNODE, errno);
334		return (0);
335	}
336	*s = _elf_snode_init;
337	ELFMUTEXINIT(&s->sb_scn.s_mutex);
338	s->sb_scn.s_myflags = SF_ALLOC | SF_READY;
339	s->sb_scn.s_shdr = &s->sb_shdr;
340	return (s);
341}
342
343
344
345int
346_elf_ehdr(Elf * elf, int inplace)
347{
348	NOTE(ASSUMING_PROTECTED(*elf))
349	register size_t	fsz;		/* field size */
350	Elf_Data	dst, src;
351
352	fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version);
353	if (fsz > elf->ed_fsz) {
354		_elf_seterr(EFMT_EHDRSZ, 0);
355		return (-1);
356	}
357	if (inplace && (fsz >= sizeof (Ehdr))) {
358		/*
359		 * The translated Ehdr will fit over the original Ehdr.
360		 */
361		/* LINTED */
362		elf->ed_ehdr = (Ehdr *)elf->ed_ident;
363		elf->ed_status = ES_COOKED;
364	} else {
365		elf->ed_ehdr = malloc(sizeof (Ehdr));
366		if (elf->ed_ehdr == 0) {
367			_elf_seterr(EMEM_EHDR, errno);
368			return (-1);
369		}
370		elf->ed_myflags |= EDF_EHALLOC;
371	}
372
373	/*
374	 * Memory size >= fsz, because otherwise the memory version
375	 * loses information and cannot accurately implement the
376	 * file.
377	 */
378
379	src.d_buf = (Elf_Void *)elf->ed_ident;
380	src.d_type = ELF_T_EHDR;
381	src.d_size = fsz;
382	src.d_version = elf->ed_version;
383	dst.d_buf = (Elf_Void *)elf->ed_ehdr;
384	dst.d_size = sizeof (Ehdr);
385	dst.d_version = EV_CURRENT;
386
387	if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) ||
388	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
389		if (elf->ed_myflags & EDF_EHALLOC) {
390			elf->ed_myflags &= ~EDF_EHALLOC;
391			free(elf->ed_ehdr);
392		}
393		elf->ed_ehdr = 0;
394		return (-1);
395	}
396
397	if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) {
398		_elf_seterr(EREQ_CLASS, 0);
399		if (elf->ed_myflags & EDF_EHALLOC) {
400			elf->ed_myflags &= ~EDF_EHALLOC;
401			free(elf->ed_ehdr);
402		}
403		elf->ed_ehdr = 0;
404		return (-1);
405	}
406
407	if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) {
408		_elf_seterr(EFMT_VER2, 0);
409		if (elf->ed_myflags & EDF_EHALLOC) {
410			elf->ed_myflags &= ~EDF_EHALLOC;
411			free(elf->ed_ehdr);
412		}
413		elf->ed_ehdr = 0;
414		return (-1);
415	}
416
417	return (0);
418}
419
420
421
422int
423_elf_phdr(Elf * elf, int inplace)
424{
425	NOTE(ASSUMING_PROTECTED(*elf))
426	register size_t		fsz, msz;
427	Elf_Data		dst, src;
428	Ehdr *			eh = elf->ed_ehdr;	/* must be present */
429	unsigned		work;
430
431	if (eh->e_phnum == 0)
432		return (0);
433
434	fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version);
435	if (eh->e_phentsize != fsz) {
436		_elf_seterr(EFMT_PHDRSZ, 0);
437		return (-1);
438	}
439
440	fsz *= eh->e_phnum;
441	ELFACCESSDATA(work, _elf_work)
442	msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum;
443	if ((eh->e_phoff == 0) ||
444	    ((fsz + eh->e_phoff) > elf->ed_fsz)) {
445		_elf_seterr(EFMT_PHTAB, 0);
446		return (-1);
447	}
448
449	if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) {
450		elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
451		elf->ed_status = ES_COOKED;
452	} else {
453		if ((elf->ed_phdr = malloc(msz)) == 0) {
454			_elf_seterr(EMEM_PHDR, errno);
455			return (-1);
456		}
457		elf->ed_myflags |= EDF_PHALLOC;
458	}
459	src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
460	src.d_type = ELF_T_PHDR;
461	src.d_size = fsz;
462	src.d_version = elf->ed_version;
463	dst.d_buf = elf->ed_phdr;
464	dst.d_size = msz;
465	dst.d_version = work;
466	if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) ||
467	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
468		if (elf->ed_myflags & EDF_PHALLOC) {
469			elf->ed_myflags &= ~EDF_PHALLOC;
470			free(elf->ed_phdr);
471		}
472		elf->ed_phdr = 0;
473		return (-1);
474	}
475	elf->ed_phdrsz = msz;
476	return (0);
477}
478
479
480
481int
482_elf_shdr(Elf * elf, int inplace)
483{
484	NOTE(ASSUMING_PROTECTED(*elf))
485	register size_t		fsz, msz;
486	size_t			scncnt;
487	Elf_Data		dst, src;
488	register Ehdr		*eh = elf->ed_ehdr;	/* must be present */
489
490	if ((eh->e_shnum == 0) && (eh->e_shoff == 0))
491		return (0);
492
493	fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version);
494	if (eh->e_shentsize != fsz) {
495		_elf_seterr(EFMT_SHDRSZ, 0);
496		return (-1);
497	}
498	/*
499	 * If we are dealing with a file with 'extended section
500	 * indexes' - then we need to load the first section
501	 * header.  The actual section count is stored in
502	 * Shdr[0].sh_size.
503	 */
504	if ((scncnt = eh->e_shnum) == 0) {
505		Shdr	sh;
506		if ((eh->e_shoff == 0) ||
507		    (elf->ed_fsz <= eh->e_shoff) ||
508		    (elf->ed_fsz - eh->e_shoff < fsz)) {
509			_elf_seterr(EFMT_SHTAB, 0);
510			return (-1);
511		}
512		src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
513		src.d_type = ELF_T_SHDR;
514		src.d_size = fsz;
515		src.d_version = elf->ed_version;
516		dst.d_buf = (Elf_Void *)&sh;
517		dst.d_size = sizeof (Shdr);
518		dst.d_version = EV_CURRENT;
519		if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
520		    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
521			return (-1);
522		}
523		scncnt = sh.sh_size;
524	}
525
526	fsz *= scncnt;
527	msz = scncnt * sizeof (Shdr);
528	if ((eh->e_shoff == 0) ||
529	    (elf->ed_fsz <= eh->e_shoff) ||
530	    (elf->ed_fsz - eh->e_shoff < fsz)) {
531		_elf_seterr(EFMT_SHTAB, 0);
532		return (-1);
533	}
534
535	if (inplace && (fsz >= msz) &&
536	    ((eh->e_shoff % sizeof (ElfField)) == 0)) {
537		/* LINTED */
538		elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff);
539		elf->ed_status = ES_COOKED;
540	} else {
541		if ((elf->ed_shdr = malloc(msz)) == 0) {
542			_elf_seterr(EMEM_SHDR, errno);
543			return (-1);
544		}
545		elf->ed_myflags |= EDF_SHALLOC;
546	}
547	src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
548	src.d_type = ELF_T_SHDR;
549	src.d_size = fsz;
550	src.d_version = elf->ed_version;
551	dst.d_buf = (Elf_Void *)elf->ed_shdr;
552	dst.d_size = msz;
553	dst.d_version = EV_CURRENT;
554
555#if defined(__APPLE__)
556	if (elf->ed_kind == ELF_K_MACHO) {
557		struct _mach_header hdr, *mh = (struct _mach_header *)(elf->ed_image);
558		struct load_command *thisLC = (struct load_command *)(&(mh[1]));
559		int needSwap = (_MH_CIGAM == mh->magic);
560		int i,j;
561
562		Shdr *pShdr = (Shdr *)(elf->ed_shdr);
563		Shdr *SectionToShdrMap[scncnt]; /* small stack allocated array */
564		Shdr **pMap = SectionToShdrMap;
565		Shdr *pSymTab = NULL;
566
567		bzero(pShdr, sizeof(Shdr));
568		SectionToShdrMap[0] = pShdr;
569		pMap++; /* By Mach-o convention the n_sect ordinal index is one-based */
570		pShdr++; /* By ELF convention the first section header is unused */
571
572		if (needSwap) {
573			hdr = *mh;
574			mh = &hdr;
575			_swap_mh(mh);
576		}
577
578		for (i = 0; i < mh->ncmds; i++) {
579			int cmd = thisLC->cmd, cmdsize = thisLC->cmdsize;
580
581			if (needSwap) {
582				SWAP32(cmd);
583				SWAP32(cmdsize);
584			}
585
586			switch(cmd) {
587				case _LC_SEGMENT:
588				{
589					struct _segcmd seg, *thisSG = (struct _segcmd *)thisLC;
590					struct _sect sect, *section_ptr, *thisSect = (struct _sect *)(&(thisSG[1]));
591
592					if (needSwap) {
593						seg = *thisSG;
594						thisSG = &seg;
595						_swapsegcmd(thisSG);
596					}
597
598					for (j = 0; j < thisSG->nsects; ++j) {
599						int primary;
600
601						section_ptr = thisSect + j;
602
603						if (needSwap) {
604							sect = *section_ptr;
605							section_ptr = &sect;
606							_swapsect(section_ptr);
607						}
608
609						primary = (0 == strcmp(thisSG->segname, SEG_TEXT)) ||
610								  (0 == strcmp(thisSG->segname, SEG_DATA));
611
612						pShdr->sh_name = (_elf_word)elf_macho_str_cookie(section_ptr->sectname, primary);
613						pShdr->sh_type = SHT_UNKNOWN12;
614						pShdr->sh_flags = 0;
615						pShdr->sh_addr = (_elf_addr)section_ptr->addr;
616						pShdr->sh_offset = (_elf_off)section_ptr->offset;
617						pShdr->sh_size = section_ptr->size;
618						pShdr->sh_link = _SHN_MACHO;
619						pShdr->sh_info = STTSect(section_ptr->sectname);
620						pShdr->sh_addralign = section_ptr->align;
621						pShdr->sh_entsize = 0;
622						*pMap = pShdr;
623						pMap++;
624						pShdr++;
625					}
626					break;
627				}
628
629				case LC_SYMTAB:
630				{
631					struct symtab_command symt, *thisST = (struct symtab_command *)thisLC;
632
633					if (needSwap) {
634						symt = *thisST;
635						thisST = &symt;
636						__swap_symtab_command(thisST);
637					}
638
639					pShdr->sh_name = (_elf_word)elf_macho_str_cookie("__symbol_table", 1);
640					pShdr->sh_type = SHT_STRTAB; /* Must yield ELF_T_BYTE to allow the sh_entsize used below! */
641					pShdr->sh_flags = 0;
642					pShdr->sh_addr = (_elf_addr)(thisST->symoff);
643					pShdr->sh_offset = (_elf_off)(thisST->symoff);
644					pShdr->sh_size = thisST->nsyms * sizeof (struct _nlist);
645					pShdr->sh_link = _SHN_MACHO;
646					pShdr->sh_info = 0;
647					pShdr->sh_addralign = _addralign;
648					pShdr->sh_entsize = sizeof(struct _nlist);
649					pSymTab = pShdr;
650					pShdr++;
651
652					pShdr->sh_name = (_elf_word)elf_macho_str_cookie("__dir_str_table", 1);
653					pShdr->sh_type = SHT_STRTAB; /* Must yield ELF_T_BYTE to allow the sh_entsize used below! */
654					pShdr->sh_flags = 0;
655					pShdr->sh_addr = (_elf_addr)(thisST->stroff);
656					pShdr->sh_offset = (_elf_off)(thisST->stroff);
657					pShdr->sh_size = thisST->strsize;
658					pShdr->sh_link = _SHN_MACHO;
659					pShdr->sh_info = 0;
660					pShdr->sh_addralign = 1;
661					pShdr->sh_entsize = 0;
662					pShdr++;
663					break;
664				}
665
666				default:
667					break;
668			}
669
670			thisLC = (struct load_command *) ((caddr_t) thisLC + cmdsize);
671		}
672
673		src.d_buf = (Elf_Void *)elf->ed_shdr;
674		src.d_type = ELF_T_SHDR;
675		src.d_size = fsz;
676
677		if (NULL != pSymTab) {
678			struct _nlist *nsym = (struct _nlist *)(elf->ed_image + pSymTab->sh_addr);
679			struct _nlist *pEnd = nsym + (pSymTab->sh_size/pSymTab->sh_entsize);
680			pMap = SectionToShdrMap;
681
682			if (mprotect((char *)elf->ed_image, elf->ed_imagesz,
683						PROT_READ|PROT_WRITE) == -1) {
684				_elf_seterr(EIO_VM, errno);
685				return (-1);
686			}
687
688			while (nsym < pEnd) {
689
690				if (needSwap) {
691					SWAP32(nsym->n_un.n_strx);
692					SWAP16(nsym->n_desc);
693					_SWAPVAL(nsym->n_value);
694				}
695
696				if (nsym->n_type & N_STAB) { /* Detect C++ methods */
697
698					switch(nsym->n_type) {
699					case N_FUN:
700						nsym->n_desc = STT_FUNC;
701						break;
702					case N_GSYM:
703						nsym->n_desc = STT_OBJECT;
704						break;
705					default:
706						break;
707					}
708
709				} else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) ||
710					(N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) {
711					nsym->n_desc = SectionToShdrMap[nsym->n_sect]->sh_info;
712				} else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) &&
713							nsym->n_sect == NO_SECT) {
714					nsym->n_desc = STT_OBJECT; /* Common symbol */
715				} else {
716					/* NOTHING don't mess with other types of symbols */
717				}
718				nsym++;
719			}
720		}
721	}
722#endif /* __APPLE__ */
723
724	if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
725	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) ||
726	    (_elf_prepscn(elf, scncnt) != OK_YES)) {
727		if (elf->ed_myflags & EDF_SHALLOC) {
728			elf->ed_myflags &= ~EDF_SHALLOC;
729			free(elf->ed_shdr);
730		}
731		elf->ed_shdr = 0;
732		return (-1);
733	}
734	return (0);
735}
736