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