#ifdef SHLIB
#include "shlib.h"
#endif
#if !(defined(KLD) && defined(__STATIC__))
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach.h>
#else
#include <mach/kern_return.h>
#endif
#include <string.h>
#include <stdarg.h>
#include <mach-o/loader.h>
#include "stuff/arch.h"
#include "ld.h"
#ifndef RLD
#include "specs.h"
#include "live_refs.h"
#include "objects.h"
#include "sections.h"
__private_extern__ struct segment_spec *segment_specs = NULL;
__private_extern__ unsigned long nsegment_specs = 0;
__private_extern__
struct segment_spec *
create_segment_spec(
char *segname)
{
unsigned long i;
for(i = 0; i < nsegment_specs; i++){
if(strcmp(segment_specs[i].segname, segname) == 0)
return(&(segment_specs[i]));
}
segment_specs = reallocate(segment_specs, (nsegment_specs + 1) *
sizeof(struct segment_spec));
memset(&(segment_specs[nsegment_specs]), '\0',
sizeof(struct segment_spec));
segment_specs[nsegment_specs].segname = segname;
return(&(segment_specs[nsegment_specs++]));
}
__private_extern__
struct section_spec *
create_section_spec(
struct segment_spec *seg_spec,
char *sectname)
{
unsigned long i;
for(i = 0; i < seg_spec->nsection_specs; i++){
if(strcmp(seg_spec->section_specs[i].sectname, sectname) == 0)
return(&(seg_spec->section_specs[i]));
}
seg_spec->section_specs = reallocate(seg_spec->section_specs,
(seg_spec->nsection_specs + 1) *
sizeof(struct section_spec));
memset(&(seg_spec->section_specs[seg_spec->nsection_specs]), '\0',
sizeof(struct section_spec));
seg_spec->section_specs[seg_spec->nsection_specs].sectname = sectname;
return(&(seg_spec->section_specs[seg_spec->nsection_specs++]));
}
__private_extern__
struct segment_spec *
lookup_segment_spec(
char *segname)
{
unsigned long i;
for(i = 0; i < nsegment_specs; i++){
if(strcmp(segment_specs[i].segname, segname) == 0)
return(&(segment_specs[i]));
}
return(NULL);
}
__private_extern__
struct section_spec *
lookup_section_spec(
char *segname,
char *sectname)
{
unsigned long i, j;
for(i = 0; i < nsegment_specs; i++){
if(strcmp(segment_specs[i].segname, segname) == 0){
for(j = 0; j < segment_specs[i].nsection_specs; j++){
if(strcmp(segment_specs[i].section_specs[j].sectname,
sectname) == 0)
return(&(segment_specs[i].section_specs[j]));
}
}
}
return(NULL);
}
__private_extern__
void
process_section_specs(void)
{
unsigned long i, j, k;
struct merged_section *ms;
struct section_spec *sect_spec;
struct section s = { {0} };
for(i = 0; i < nsegment_specs; i++){
for(j = i + 1; j < nsegment_specs; j++){
if(strncmp(segment_specs[i].segname, segment_specs[j].segname,
sizeof(s.segname)) == 0)
error("segment names: %s and %s not unique to %lu "
"characters\n", segment_specs[i].segname,
segment_specs[j].segname, sizeof(s.segname));
}
for(j = 0; j < segment_specs[i].nsection_specs; j++){
for(k = j + 1; k < segment_specs[i].nsection_specs; k++){
if(strncmp(segment_specs[i].section_specs[j].sectname,
segment_specs[i].section_specs[k].sectname,
sizeof(s.sectname)) == 0)
error("section names: %s and %s (in segment %s) not unique "
"to %lu characters\n",
segment_specs[i].section_specs[j].sectname,
segment_specs[i].section_specs[k].sectname,
segment_specs[i].segname, sizeof(s.segname));
}
}
}
for(i = 0; i < nsegment_specs; i++){
for(j = 0; j < segment_specs[i].nsection_specs; j++){
if(segment_specs[i].section_specs[j].processed)
continue;
ms = lookup_merged_section(segment_specs[i].segname,
segment_specs[i].section_specs[j].sectname);
sect_spec = &(segment_specs[i].section_specs[j]);
if(ms == NULL){
if(sect_spec->contents_filename == NULL){
if(sect_spec->align_specified)
warning("no (%s,%s) section in output file, "
"specified alignment not used",
segment_specs[i].segname,
sect_spec->sectname);
if(sect_spec->order_filename)
warning("no (%s,%s) section in output file, "
"-sectorder file: %s not used",
segment_specs[i].segname,
sect_spec->sectname,
sect_spec->order_filename);
}
else{
if(sect_spec->order_filename)
warning("section (%s,%s) is to be created from "
"file: %s and is meaningless to have a "
"-sectorder file: %s for it",
segment_specs[i].segname,
sect_spec->sectname,
sect_spec->contents_filename,
sect_spec->order_filename);
strncpy(s.segname, segment_specs[i].segname,
sizeof(s.segname));
strncpy(s.sectname, sect_spec->sectname,
sizeof(s.segname));
ms = create_merged_section(&s);
ms->contents_filename = sect_spec->contents_filename;
ms->file_addr = sect_spec->file_addr;
ms->file_size = sect_spec->file_size;
if(sect_spec->align_specified)
ms->s.align = sect_spec->align;
else
ms->s.align = defaultsectalign;
ms->s.size = rnd(sect_spec->file_size,
1 << ms->s.align);
ms->s.flags |= S_ATTR_NO_DEAD_STRIP;
}
sect_spec->processed = TRUE;
continue;
}
if(sect_spec->contents_filename != NULL)
error("section (%.16s,%.16s) exist in the loaded object "
"files and can't be created from the file: %s",
ms->s.segname, ms->s.sectname,
sect_spec->contents_filename);
else{
if(sect_spec->align_specified){
if(ms->s.align > sect_spec->align)
warning("specified alignment (0x%x) for section (%s"
",%s) not used (less than the required "
"alignment in the input files (0x%x))",
(unsigned int)(1 << sect_spec->align),
segment_specs[i].segname,
sect_spec->sectname,
(unsigned int)(1 << ms->s.align));
else
ms->s.align = sect_spec->align;
}
if(sect_spec->order_filename != NULL){
if(arch_flag.cputype == CPU_TYPE_I860)
warning("sections can't be ordered in I860 cputype "
"objects (-sectorder %s %s %s ignored)",
segment_specs[i].segname,
sect_spec->sectname,
sect_spec->order_filename);
else if(filetype == MH_DYLIB &&
strcmp(ms->s.segname, SEG_OBJC) == 0 &&
strcmp(ms->s.sectname, SECT_OBJC_MODULES) == 0){
warning("for MH_DYLIB output files section ("
SEG_OBJC "," SECT_OBJC_MODULES ") can't be "
"ordered (-sectorder %s %s %s ignored)",
segment_specs[i].segname, sect_spec->sectname,
sect_spec->order_filename);
}
else if((ms->s.flags & S_ATTR_DEBUG) == S_ATTR_DEBUG){
warning("debug sections can't be ordered as they "
"won't appear in the output (-sectorder %s "
"%s %s ignored)", segment_specs[i].segname,
sect_spec->sectname,
sect_spec->order_filename);
}
else{
ms->order_filename = sect_spec->order_filename;
ms->order_addr = sect_spec->order_addr;
ms->order_size = sect_spec->order_size;
}
}
}
sect_spec->processed = TRUE;
}
}
}
__private_extern__
void
process_segment_specs(void)
{
unsigned long i;
struct merged_segment *msg;
for(i = 0; i < nsegment_specs; i++){
if(segment_specs[i].processed)
continue;
msg = lookup_merged_segment(segment_specs[i].segname);
if(msg != NULL){
if(segment_specs[i].addr_specified){
if(segment_specs[i].addr % segalign != 0){
error("address: 0x%x specified for segment: %s not a "
"multiple of the segment alignment (0x%x)",
(unsigned int)(segment_specs[i].addr),
segment_specs[i].segname,
(unsigned int)(segalign));
}
else{
msg->sg.vmaddr = segment_specs[i].addr;
msg->addr_set = TRUE;
}
}
if(segment_specs[i].prot_specified){
msg->sg.maxprot = segment_specs[i].maxprot;
msg->sg.initprot = segment_specs[i].initprot;
msg->prot_set = TRUE;
}
}
else{
if(filetype == MH_OBJECT &&
(segment_specs[i].addr_specified ||
segment_specs[i].prot_specified)){
warning("all named segment specifications ignored with "
"MH_OBJECT output file format");
return;
}
if(segment_specs[i].addr_specified)
warning("segment: %s not in output file, specified address "
"not used", segment_specs[i].segname);
if(segment_specs[i].prot_specified)
warning("segment: %s not in output file, specified "
"protection not used", segment_specs[i].segname);
}
}
}
#endif
#ifdef DEBUG
#ifndef RLD
__private_extern__
void
print_segment_specs(void)
{
unsigned long i, j;
print("Segment specs\n");
for(i = 0; i < nsegment_specs; i++){
print(" segname = %s\n", segment_specs[i].segname);
if(segment_specs[i].addr_specified)
print("\taddr_specified TRUE\n"
"\taddr 0x%08x\n", (unsigned int)(segment_specs[i].addr));
else
print("\taddr_specified FALSE\n");
if(segment_specs[i].prot_specified){
print("\tprot_specified TRUE\n");
print("\tmaxprot ");
print_prot(segment_specs[i].maxprot);
print("\n");
print("\tinitprot ");
print_prot(segment_specs[i].initprot);
print("\n");
}
else{
print("\tprot_specified FALSE\n");
}
print("\tnsection_specs %lu\n", segment_specs[i].nsection_specs);
print("\tSection specs\n");
for(j = 0; j < segment_specs[i].nsection_specs; j++){
print("\t sectname %s\n",
segment_specs[i].section_specs[j].sectname);
if(segment_specs[i].section_specs[j].contents_filename != NULL){
print("\t contents_filename %s\n",
segment_specs[i].section_specs[j].contents_filename);
print("\t file_addr 0x%x\n", (unsigned int)
(segment_specs[i].section_specs[j].file_addr));
print("\t file_size %lu\n",
segment_specs[i].section_specs[j].file_size);
}
if(segment_specs[i].section_specs[j].order_filename != NULL){
print("\t order_filename %s\n",
segment_specs[i].section_specs[j].order_filename);
print("\t order_addr 0x%x\n", (unsigned int)
(segment_specs[i].section_specs[j].order_addr));
print("\t order_size %lu\n",
segment_specs[i].section_specs[j].order_size);
}
if(segment_specs[i].section_specs[j].align_specified)
print("\t align_specified TRUE\n"
"\t align %lu\n",
segment_specs[i].section_specs[j].align);
else
print("\t align_specified FALSE\n");
}
}
}
#endif
__private_extern__
void
print_prot(
vm_prot_t prot)
{
if(prot & VM_PROT_READ)
print("r");
else
print("-");
if(prot & VM_PROT_WRITE)
print("w");
else
print("-");
if(prot & VM_PROT_EXECUTE)
print("x");
else
print("-");
}
#endif