mirror of
https://github.com/darlinghq/cctools-port.git
synced 2024-11-27 06:00:31 +00:00
344 lines
10 KiB
C
344 lines
10 KiB
C
/*
|
|
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "stuff/errors.h"
|
|
#include "stuff/breakout.h"
|
|
#include "stuff/rnd.h"
|
|
|
|
/* used by error routines as the name of the program */
|
|
char *progname = NULL;
|
|
|
|
static void usage(
|
|
void);
|
|
|
|
static void process(
|
|
struct arch *archs,
|
|
uint32_t narchs);
|
|
|
|
static void setup_object_symbolic_info(
|
|
struct object *object);
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
char **argv,
|
|
char **envp)
|
|
{
|
|
uint32_t i;
|
|
char *input, *output;
|
|
struct arch *archs;
|
|
uint32_t narchs;
|
|
|
|
progname = argv[0];
|
|
input = NULL;
|
|
output = NULL;
|
|
archs = NULL;
|
|
narchs = 0;
|
|
for(i = 1; i < argc; i++){
|
|
if(strcmp(argv[i], "-o") == 0){
|
|
if(i + 1 == argc){
|
|
error("missing argument(s) to: %s option", argv[i]);
|
|
usage();
|
|
}
|
|
if(output != NULL){
|
|
error("more than one: %s option specified", argv[i]);
|
|
usage();
|
|
}
|
|
output = argv[i+1];
|
|
i++;
|
|
}
|
|
else{
|
|
if(input != NULL){
|
|
error("more than one input file specified (%s and %s)",
|
|
argv[i], input);
|
|
usage();
|
|
}
|
|
input = argv[i];
|
|
}
|
|
}
|
|
if(input == NULL || output == NULL)
|
|
usage();
|
|
|
|
breakout(input, &archs, &narchs, FALSE);
|
|
if(errors)
|
|
exit(EXIT_FAILURE);
|
|
|
|
checkout(archs, narchs);
|
|
|
|
process(archs, narchs);
|
|
|
|
writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL);
|
|
|
|
if(errors)
|
|
return(EXIT_FAILURE);
|
|
else
|
|
return(EXIT_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
* usage() prints the current usage message and exits indicating failure.
|
|
*/
|
|
static
|
|
void
|
|
usage(
|
|
void)
|
|
{
|
|
fprintf(stderr, "Usage: %s input -o output\n", progname);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static
|
|
void
|
|
process(
|
|
struct arch *archs,
|
|
uint32_t narchs)
|
|
{
|
|
uint32_t i, j, offset, size;
|
|
struct object *object;
|
|
|
|
for(i = 0; i < narchs; i++){
|
|
if(archs[i].type == OFILE_ARCHIVE){
|
|
for(j = 0; j < archs[i].nmembers; j++){
|
|
if(archs[i].members[j].type == OFILE_Mach_O){
|
|
object = archs[i].members[j].object;
|
|
setup_object_symbolic_info(object);
|
|
}
|
|
}
|
|
/*
|
|
* Reset the library offsets and size.
|
|
*/
|
|
offset = 0;
|
|
for(j = 0; j < archs[i].nmembers; j++){
|
|
archs[i].members[j].offset = offset;
|
|
size = 0;
|
|
if(archs[i].members[j].member_long_name == TRUE){
|
|
size = rnd(archs[i].members[j].member_name_size,
|
|
sizeof(int32_t));
|
|
archs[i].toc_long_name = TRUE;
|
|
}
|
|
if(archs[i].members[j].object != NULL){
|
|
size += archs[i].members[j].object->object_size
|
|
- archs[i].members[j].object->input_sym_info_size
|
|
+ archs[i].members[j].object->output_sym_info_size;
|
|
sprintf(archs[i].members[j].ar_hdr->ar_size, "%-*ld",
|
|
(int)sizeof(archs[i].members[j].ar_hdr->ar_size),
|
|
(long)(size));
|
|
/*
|
|
* This has to be done by hand because sprintf puts a
|
|
* null at the end of the buffer.
|
|
*/
|
|
memcpy(archs[i].members[j].ar_hdr->ar_fmag, ARFMAG,
|
|
(int)sizeof(archs[i].members[j].ar_hdr->ar_fmag));
|
|
}
|
|
else{
|
|
size += archs[i].members[j].unknown_size;
|
|
}
|
|
offset += sizeof(struct ar_hdr) + size;
|
|
}
|
|
archs[i].library_size = offset;
|
|
}
|
|
else if(archs[i].type == OFILE_Mach_O){
|
|
object = archs[i].object;
|
|
setup_object_symbolic_info(object);
|
|
}
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
setup_object_symbolic_info(
|
|
struct object *object)
|
|
{
|
|
uint32_t output_indirectsym_pad_diff;
|
|
|
|
if(object->st != NULL && object->st->nsyms != 0){
|
|
if(object->mh != NULL){
|
|
object->output_symbols = (struct nlist *)
|
|
(object->object_addr + object->st->symoff);
|
|
if(object->object_byte_sex != get_host_byte_sex())
|
|
swap_nlist(object->output_symbols,
|
|
object->st->nsyms,
|
|
get_host_byte_sex());
|
|
object->output_symbols64 = NULL;
|
|
}
|
|
else{
|
|
object->output_symbols64 = (struct nlist_64 *)
|
|
(object->object_addr + object->st->symoff);
|
|
if(object->object_byte_sex != get_host_byte_sex())
|
|
swap_nlist_64(object->output_symbols64,
|
|
object->st->nsyms,
|
|
get_host_byte_sex());
|
|
object->output_symbols = NULL;
|
|
}
|
|
object->output_nsymbols = object->st->nsyms;
|
|
object->output_strings =
|
|
object->object_addr + object->st->stroff;
|
|
object->output_strings_size = object->st->strsize;
|
|
if(object->mh != NULL){
|
|
object->input_sym_info_size =
|
|
object->st->nsyms * sizeof(struct nlist) +
|
|
object->st->strsize;
|
|
}
|
|
else{
|
|
object->input_sym_info_size =
|
|
object->st->nsyms * sizeof(struct nlist_64) +
|
|
object->st->strsize;
|
|
}
|
|
}
|
|
output_indirectsym_pad_diff = 0;
|
|
if(object->dyst != NULL){
|
|
object->output_ilocalsym = object->dyst->ilocalsym;
|
|
object->output_nlocalsym = object->dyst->nlocalsym;
|
|
object->output_iextdefsym = object->dyst->iextdefsym;
|
|
object->output_nextdefsym = object->dyst->nextdefsym;
|
|
object->output_iundefsym = object->dyst->iundefsym;
|
|
object->output_nundefsym = object->dyst->nundefsym;
|
|
object->output_indirect_symtab = (uint32_t *)
|
|
(object->object_addr + object->dyst->indirectsymoff);
|
|
object->output_loc_relocs = (struct relocation_info *)
|
|
(object->object_addr + object->dyst->locreloff);
|
|
if(object->split_info_cmd != NULL){
|
|
object->output_split_info_data =
|
|
(object->object_addr + object->split_info_cmd->dataoff);
|
|
object->output_split_info_data_size =
|
|
object->split_info_cmd->datasize;
|
|
}
|
|
if(object->func_starts_info_cmd != NULL){
|
|
object->output_func_start_info_data =
|
|
(object->object_addr + object->func_starts_info_cmd->dataoff);
|
|
object->output_func_start_info_data_size =
|
|
object->func_starts_info_cmd->datasize;
|
|
}
|
|
if(object->data_in_code_cmd != NULL){
|
|
object->output_data_in_code_info_data =
|
|
(object->object_addr + object->data_in_code_cmd->dataoff);
|
|
object->output_data_in_code_info_data_size =
|
|
object->data_in_code_cmd->datasize;
|
|
}
|
|
if(object->code_sign_drs_cmd != NULL){
|
|
object->output_code_sign_drs_info_data =
|
|
(object->object_addr + object->code_sign_drs_cmd->dataoff);
|
|
object->output_code_sign_drs_info_data_size =
|
|
object->code_sign_drs_cmd->datasize;
|
|
}
|
|
object->output_ext_relocs = (struct relocation_info *)
|
|
(object->object_addr + object->dyst->extreloff);
|
|
object->output_tocs =
|
|
(struct dylib_table_of_contents *)
|
|
(object->object_addr + object->dyst->tocoff);
|
|
object->output_ntoc = object->dyst->ntoc;
|
|
if(object->mh != NULL){
|
|
object->output_mods = (struct dylib_module *)
|
|
(object->object_addr + object->dyst->modtaboff);
|
|
object->output_mods64 = NULL;
|
|
}
|
|
else{
|
|
object->output_mods64 = (struct dylib_module_64 *)
|
|
(object->object_addr + object->dyst->modtaboff);
|
|
object->output_mods = NULL;
|
|
}
|
|
object->output_nmodtab = object->dyst->nmodtab;
|
|
object->output_refs = (struct dylib_reference *)
|
|
(object->object_addr + object->dyst->extrefsymoff);
|
|
object->output_nextrefsyms = object->dyst->nextrefsyms;
|
|
if(object->hints_cmd != NULL){
|
|
object->output_hints = (struct twolevel_hint *)
|
|
(object->object_addr +
|
|
object->hints_cmd->offset);
|
|
}
|
|
if(object->code_sig_cmd != NULL){
|
|
object->output_code_sig_data = object->object_addr +
|
|
object->code_sig_cmd->dataoff;
|
|
object->output_code_sig_data_size =
|
|
object->code_sig_cmd->datasize;
|
|
}
|
|
object->input_sym_info_size +=
|
|
object->dyst->nlocrel *
|
|
sizeof(struct relocation_info) +
|
|
object->dyst->nextrel *
|
|
sizeof(struct relocation_info) +
|
|
object->dyst->ntoc *
|
|
sizeof(struct dylib_table_of_contents)+
|
|
object->dyst->nextrefsyms *
|
|
sizeof(struct dylib_reference);
|
|
if(object->split_info_cmd != NULL)
|
|
object->input_sym_info_size += object->split_info_cmd->datasize;
|
|
if(object->func_starts_info_cmd != NULL)
|
|
object->input_sym_info_size +=
|
|
object->func_starts_info_cmd->datasize;
|
|
if(object->data_in_code_cmd != NULL)
|
|
object->input_sym_info_size +=
|
|
object->data_in_code_cmd->datasize;
|
|
if(object->code_sign_drs_cmd != NULL)
|
|
object->input_sym_info_size +=
|
|
object->code_sign_drs_cmd->datasize;
|
|
if(object->mh != NULL){
|
|
object->input_sym_info_size +=
|
|
object->dyst->nmodtab *
|
|
sizeof(struct dylib_module) +
|
|
object->dyst->nindirectsyms *
|
|
sizeof(uint32_t);
|
|
}
|
|
else{
|
|
object->input_sym_info_size +=
|
|
object->dyst->nmodtab *
|
|
sizeof(struct dylib_module_64)+
|
|
object->dyst->nindirectsyms *
|
|
sizeof(uint32_t) +
|
|
object->input_indirectsym_pad;
|
|
if(object->input_indirectsym_pad == 0 &&
|
|
(object->dyst->nindirectsyms % 2) != 0)
|
|
output_indirectsym_pad_diff = 4;
|
|
}
|
|
if(object->hints_cmd != NULL){
|
|
object->input_sym_info_size +=
|
|
object->hints_cmd->nhints *
|
|
sizeof(struct twolevel_hint);
|
|
}
|
|
if(object->code_sig_cmd != NULL){
|
|
object->input_sym_info_size = rnd(object->input_sym_info_size,
|
|
16);
|
|
object->input_sym_info_size += object->code_sig_cmd->datasize;
|
|
}
|
|
if(output_indirectsym_pad_diff != 0){
|
|
if(object->output_ntoc != 0)
|
|
object->dyst->tocoff += output_indirectsym_pad_diff;
|
|
if(object->output_nmodtab != 0)
|
|
object->dyst->modtaboff += output_indirectsym_pad_diff;
|
|
if(object->output_nextrefsyms != 0)
|
|
object->dyst->extrefsymoff += output_indirectsym_pad_diff;
|
|
if(object->output_strings_size != 0)
|
|
object->st->stroff += output_indirectsym_pad_diff;
|
|
object->seg_linkedit64->filesize += output_indirectsym_pad_diff;
|
|
if(object->seg_linkedit64->filesize >
|
|
object->seg_linkedit64->vmsize)
|
|
object->seg_linkedit64->vmsize +=
|
|
output_indirectsym_pad_diff;
|
|
}
|
|
}
|
|
object->output_sym_info_size =
|
|
object->input_sym_info_size + output_indirectsym_pad_diff;
|
|
}
|