#include "as.h"
#include <stdlib.h>
#include <strings.h>
#include "sections.h"
#include "obstack.h"
#include "xmalloc.h"
#include "frags.h"
#include "messages.h"
#include "symbols.h"
frchainS *frchain_root = NULL;
frchainS *frchain_now = NULL;
int now_seg = 0;
int now_subseg = 0;
void
sections_begin(
void)
{
}
frchainS *
section_new(
char *segname,
char *sectname,
uint32_t type,
uint32_t attributes,
uint32_t sizeof_stub)
{
frchainS *frcP;
frchainS **lastPP;
uint32_t last_nsect;
if(frags.chunk_size == 0)
_obstack_begin(&frags, 5000, 4,
obstack_chunk_alloc, obstack_chunk_free);
last_nsect = 0;
for(frcP = *(lastPP = &frchain_root);
frcP != NULL;
frcP = *(lastPP = &frcP->frch_next)){
if(strncmp(frcP->frch_section.segname, segname,
sizeof(frcP->frch_section.segname)) == 0 &&
strncmp(frcP->frch_section.sectname, sectname,
sizeof(frcP->frch_section.sectname)) == 0)
break;
last_nsect = frcP->frch_nsect;
}
if(frcP != NULL){
if((frcP->frch_section.flags & SECTION_TYPE) != type){
as_warn("section type does not match previous section type");
}
if(type == S_SYMBOL_STUBS &&
frcP->frch_section.reserved2 != sizeof_stub){
as_warn("section stub size does not match previous section "
"stub size");
}
frcP->frch_section.flags |= attributes;
}
if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL ||
type == S_THREAD_LOCAL_ZEROFILL)){
if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL)
now_seg = frcP->frch_nsect;
return(frcP);
}
if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL){
if(frag_now != NULL){
frag_now->fr_fix = obstack_next_free(&frags) -
frag_now->fr_literal;
frag_wane(frag_now);
}
(void)obstack_finish(&frags);
}
if(frcP != NULL){
if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL)
now_seg = frcP->frch_nsect;
if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL ||
(frcP->frch_section.flags & SECTION_TYPE) ==
S_THREAD_LOCAL_ZEROFILL){
return(frcP);
}
else{
frchain_now = frcP;
if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL)
now_seg = frchain_now->frch_nsect;
frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
frag_now->fr_next = NULL;
frchain_now->frch_last->fr_next = frag_now;
frchain_now->frch_last = frag_now;
}
}
else{
frcP = (frchainS *)xmalloc(sizeof(frchainS));
memset(frcP, '\0', sizeof(frchainS));
strncpy(frcP->frch_section.segname, segname,
sizeof(frcP->frch_section.segname));
strncpy(frcP->frch_section.sectname, sectname,
sizeof(frcP->frch_section.sectname));
frcP->frch_section.flags = attributes | type;
frcP->frch_section.reserved2 = sizeof_stub;
if(last_nsect + 1 > MAX_SECT)
as_fatal("too many sections (maximum %d)\n", MAX_SECT);
frcP->frch_nsect = last_nsect + 1;
if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL)
now_seg = frcP->frch_nsect;
*lastPP = frcP;
if(type == S_ZEROFILL || type == S_THREAD_LOCAL_ZEROFILL){
return(frcP);
}
else{
frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
frag_now->fr_next = NULL;
frcP->frch_root = frag_now;
frcP->frch_last = frag_now;
frchain_now = frcP;
}
}
return(frchain_now);
}
void
section_set(
frchainS *frcP)
{
section_new(frcP->frch_section.segname, frcP->frch_section.sectname,
frcP->frch_section.flags & SECTION_TYPE,
frcP->frch_section.flags & SECTION_ATTRIBUTES,
frcP->frch_section.reserved2);
}
symbolS *
section_symbol(
frchainS *frcP)
{
if(frcP->section_symbol == NULL){
frcP->section_symbol = symbol_temp_new(frcP->frch_nsect,
0,
frcP->frch_root);
}
return(frcP->section_symbol);
}
int
seg_not_empty_p(
frchainS *frcP)
{
fragS *frag;
if(frcP == NULL)
return(0);
for(frag = frcP->frch_root; frag; frag = frag->fr_next){
if(frag->fr_fix != 0)
return 1;
}
return 0;
}
struct frchain *
get_section_by_nsect(
uint32_t nsect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == nsect)
return(frchainP);
}
return(NULL);
}
struct frchain *
get_section_by_name(
char *segname,
char *sectname)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(strncmp(frchainP->frch_section.segname, segname,
sizeof(frchainP->frch_section.segname)) == 0 &&
strncmp(frchainP->frch_section.sectname, sectname,
sizeof(frchainP->frch_section.sectname)) == 0)
return(frchainP);
}
return(NULL);
}
uint32_t
is_section_coalesced(
uint32_t n_sect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect &&
(frchainP->frch_section.flags & SECTION_TYPE) == S_COALESCED)
return(1);
}
return(0);
}
uint32_t
is_section_non_lazy_symbol_pointers(
uint32_t n_sect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect &&
(frchainP->frch_section.flags & SECTION_TYPE) ==
S_NON_LAZY_SYMBOL_POINTERS)
return(1);
}
return(0);
}
uint32_t
is_section_debug(
uint32_t n_sect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect &&
(frchainP->frch_section.flags & SECTION_ATTRIBUTES) ==
S_ATTR_DEBUG)
return(1);
}
return(0);
}
uint32_t
is_section_cstring_literals(
uint32_t n_sect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect &&
(frchainP->frch_section.flags & SECTION_TYPE) ==
S_CSTRING_LITERALS)
return(1);
}
return(0);
}
uint32_t
is_end_section_address(
uint32_t n_sect,
addressT addr)
{
struct frchain *frchainP;
uint32_t section_type;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect){
section_type = frchainP->frch_section.flags & SECTION_TYPE;
if(section_type == S_ZEROFILL ||
section_type == S_THREAD_LOCAL_ZEROFILL)
return(0);
if(frchainP->frch_last->fr_address == addr)
return(1);
else
return(0);
}
}
return(0);
}
uint32_t
section_has_fixed_size_data(
uint32_t n_sect)
{
struct frchain *frchainP;
for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
if(frchainP->frch_nsect == n_sect){
switch (frchainP->frch_section.flags & SECTION_TYPE){
case S_CSTRING_LITERALS:
case S_4BYTE_LITERALS:
case S_8BYTE_LITERALS:
case S_16BYTE_LITERALS:
case S_LITERAL_POINTERS:
case S_NON_LAZY_SYMBOL_POINTERS:
case S_LAZY_SYMBOL_POINTERS:
case S_MOD_INIT_FUNC_POINTERS:
case S_MOD_TERM_FUNC_POINTERS:
case S_INTERPOSING:
return(1);
}
}
}
return(0);
}