#ifndef USE_APPLE_SCALABLE_MALLOC
#define USE_APPLE_SCALABLE_MALLOC 0
#endif
#if USE_APPLE_SCALABLE_MALLOC
#include "scalable_malloc.h"
#endif
#include "config.h"
#include "system.h"
#include "timevar.h"
#include "hashtab.h"
#include "machmode.h"
#include "tm_p.h"
#include "langhooks.h"
#include <stdio.h>
#include <sys/stat.h>
#if !USE_APPLE_SCALABLE_MALLOC
#include "pfe-mem.h"
#endif
#include "pfe.h"
#include "pfe-header.h"
#if PFE_NO_THAW_LOAD
#define PFE_NO_THAW_LOAD_USING_MMAP 1
#if PFE_NO_THAW_LOAD_USING_MMAP
#include <sys/types.h>
#include <sys/mman.h>
#else
#include <mach/mach.h>
#include <mach/mach_error.h>
#endif
#define PFE_NO_THAW_LOAD_DIAGNOSTICS 0
#endif
const char *pfe_name = NULL;
FILE *pfe_file = NULL;
enum pfe_action pfe_operation = PFE_NOT_INITIALIZED;
pfe_compiler_state *pfe_compiler_state_ptr = 0;
pfe_freeze_thaw_ptr_t pfe_freeze_thaw_ptr_fp = NULL;
#ifdef PFE_LOW_LEVEL_TEST
#define PFE_DEBUG_MEMMGR_RANGES 1
#define fatal_error(x) do {fprintf(stderr, x); exit (1);} while (0)
#define fatal_io_error(x) fatal_error (x)
#define internal_error(x) fatal_error (x)
#define xmalloc(s) malloc(s)
#define xcalloc(n, s) calloc(n, s)
void
pfe_freeze_compiler_state (the_hdr)
void *the_hdr;
{}
void
pfe_thaw_compiler_state (hdr)
pfe_compiler_state *hdr;
{}
#endif
#ifndef PFE_DEBUG_MEMMGR_RANGES
#define PFE_DEBUG_MEMMGR_RANGES 0
#endif
#ifndef PFE_DEBUG_EXTRA_CHECKING
#define PFE_DEBUG_EXTRA_CHECKING 1
#endif
#ifndef PFE_MEMORY_STATS
#define PFE_MEMORY_STATS 1
#endif
#define PFE_INITIAL_DUMP_RANGE_TABLE_SIZE 100
#define PFE_DUMP_RANGE_TABLE_INCR 50
struct pfe_dump_memory_range {
unsigned long start_addr;
unsigned long end_addr;
unsigned long file_offset;
};
typedef struct pfe_dump_memory_range pfe_dump_memory_range;
static char *pfe_load_buffer_ptr = 0;
static unsigned int pfe_load_buffer_size = 0;
#if USE_APPLE_SCALABLE_MALLOC
static malloc_zone_t *pfe_memory_zone = 0;
#endif
static pfe_dump_memory_range *pfe_dump_range_table;
static int pfe_dump_range_table_size = 0;
static int pfe_dump_range_table_nitems = 0;
static unsigned long pfe_allowed_ptr_variance = 0;
static int pfe_memory_locked_for_dump = 0;
static void **pfe_temp_ptr = 0;
#if PFE_NO_THAW_LOAD
static unsigned long pfe_assumed_load_address = 0;
static int pfe_no_thaw_load = 0;
static unsigned long pfe_load_offset_adjust;
#endif
#if PFE_MEMORY_STATS
extern int pfe_display_memory_stats;
static size_t pfe_malloc_total_size = 0;
static int pfe_mallocs = 0;
static int pfe_callocs = 0;
static int pfe_reallocs = 0;
static int pfe_frees = 0;
static int pfe_frees_from_load_area = 0;
static int pfe_savestrings = 0;
static int pfe_freeze_ptrs = 0;
static int pfe_thaw_ptrs = 0;
#endif
#if PFE_DEBUG_EXTRA_CHECKING
static int pfe_extra_checking = 1;
#endif
static struct ht *pfe_str_hash_table;
#if PFE_MALLOC_STATS
#define PFE_S_MALLOC_TABLE_SIZE 100
#define PFE_S_MALLOC_TABLE_INCR 50
struct pfe_s_malloc_entry {
enum pfe_alloc_object_kinds kind;
unsigned long size;
unsigned long count;
};
typedef struct pfe_s_malloc_entry pfe_s_malloc_entry;
static pfe_s_malloc_entry *pfe_s_malloc_table;
static int pfe_s_malloc_table_size = 0;
static int pfe_s_malloc_table_nitems = 0;
#define DEF_PFE_ALLOC(sym, str) str,
char *pfe_alloc_object_kinds_names[PFE_ALLOC_NBR_OF_KINDS] = {
#include "pfe-config.def"
};
#undef DEF_PFE_ALLOC
#endif
static void pfe_assign_dump_range_offsets PARAMS ((int));
static void pfe_add_dump_range PARAMS ((unsigned long, unsigned long));
static hashnode pfe_alloc_str_node PARAMS ((hash_table *));
static hashnode pfe_alloc_include_hash_node PARAMS ((hash_table *));
#if PFE_MALLOC_STATS
static void pfe_s_display_malloc_stats PARAMS ((void));
#endif
void
pfe_internal_error(msg)
const char *msg;
{
fprintf (stderr, "PFE internal error: %s.\n", msg);
internal_error ("");
}
void
pfe_init (action)
enum pfe_action action;
{
if (pfe_operation != PFE_NOT_INITIALIZED)
pfe_internal_error ("pfe_init called again before termination");
pfe_operation = action;
if (pfe_operation == PFE_DUMP)
{
enum pfe_action saved_pfe_operation;
#if USE_APPLE_SCALABLE_MALLOC
pfe_memory_zone = create_scalable_zone (0, 0);
#else
pfem_init ();
#endif
pfe_dump_range_table_size = PFE_INITIAL_DUMP_RANGE_TABLE_SIZE;
pfe_dump_range_table = (pfe_dump_memory_range *)
xmalloc (sizeof (pfe_dump_memory_range)
* pfe_dump_range_table_size);
pfe_compiler_state_ptr = (pfe_compiler_state *)
xcalloc (1, sizeof (pfe_compiler_state));
#if PFE_MALLOC_STATS
pfe_s_malloc_table_size = PFE_S_MALLOC_TABLE_SIZE;
pfe_s_malloc_table = (pfe_s_malloc_entry *)
xmalloc (sizeof (pfe_s_malloc_entry)
* pfe_s_malloc_table_size);
#endif
(*lang_hooks.pfe_lang_init) ();
#ifdef PFE_TARGET_ADDITIONS
PFE_TARGET_ADDITIONS (&pfe_compiler_state_ptr->pfe_target_additions);
#endif
saved_pfe_operation = pfe_operation;
pfe_str_hash_table = ht_create (13);
pfe_operation = saved_pfe_operation;
pfe_str_hash_table->alloc_node = pfe_alloc_str_node;
pfe_compiler_state_ptr->include_hash = ht_create (10);
pfe_compiler_state_ptr->include_hash->alloc_node = pfe_alloc_include_hash_node;
pfe_freeze_thaw_ptr_fp = pfe_freeze_ptr;
}
else if (pfe_operation == PFE_LOAD)
{
#if USE_APPLE_SCALABLE_MALLOC
pfe_memory_zone = 0;
#else
#endif
pfe_freeze_thaw_ptr_fp = pfe_thaw_ptr;
(*lang_hooks.pfe_lang_init) ();
}
else if (pfe_operation == PFE_NOP)
{
pfe_freeze_thaw_ptr_fp = (pfe_freeze_thaw_ptr_t)NULL;
}
else
pfe_internal_error ("pfe_init must specify PFE_DUMP, PFE_LOAD, "
"or PFE_NOP");
}
void
pfe_term ()
{
#if PFE_MEMORY_STATS
if (pfe_display_memory_stats
&& ((pfe_operation == PFE_LOAD)
|| (pfe_operation == PFE_DUMP)))
{
printf ("\nPFE memory utilization summary:\n");
printf ("pfe_operation = %s\n",
(pfe_operation == PFE_LOAD) ? "PFE_LOAD" : "PFE_DUMP");
printf ("pfe_malloc_total_size = %d\n", pfe_malloc_total_size);
printf ("pfe_load_buffer_size = %d\n", pfe_load_buffer_size);
printf ("pfe_mallocs = %d\n", pfe_mallocs);
printf ("pfe_callocs = %d\n", pfe_callocs);
printf ("pfe_reallocs = %d\n", pfe_reallocs);
printf ("pfe_frees = %d\n", pfe_frees);
if (pfe_operation == PFE_DUMP)
{
printf ("pfe_savestrings = %d\n",
pfe_savestrings);
printf ("pfe_freeze_ptrs = %d\n",
pfe_freeze_ptrs);
printf ("pfe_dump_range_table_nitems = %d\n",
pfe_dump_range_table_nitems);
if (pfe_load_buffer_size <= pfe_malloc_total_size)
printf ("%% overhead in dump file = ~0%%\n");
else
printf ("%% overhead in dump file = %d%%\n",
((pfe_load_buffer_size - pfe_malloc_total_size) * 100)
/ pfe_malloc_total_size);
}
else
{
printf ("pfe_frees_from_load_area = %d\n",
pfe_frees_from_load_area);
printf ("pfe_thaw_ptrs = %d\n",
pfe_thaw_ptrs);
printf ("pfe_load_buffer = 0x%x..0x%x\n",
pfe_load_buffer_ptr,
pfe_load_buffer_ptr + pfe_load_buffer_size - 1);
}
#if PFE_MALLOC_STATS
pfe_s_display_malloc_stats ();
#endif
}
#endif
if (pfe_operation == PFE_NOT_INITIALIZED)
pfe_internal_error ("pfe_term called before pfe_init");
else if (pfe_operation == PFE_DUMP)
{
#if PFE_DEBUG_MEMMGR_RANGES
int range_idx;
printf ("\n");
for (range_idx = 0; range_idx < pfe_dump_range_table_nitems; range_idx++)
printf ("pfe_term: range: @0x%08X - 0x%08X [0x%08X] %d kb\n",
pfe_dump_range_table[range_idx].start_addr,
pfe_dump_range_table[range_idx].end_addr,
pfe_dump_range_table[range_idx].file_offset,
((pfe_dump_range_table[range_idx].end_addr
- pfe_dump_range_table[range_idx].start_addr
+ 512) / 1024));
#endif
#if USE_APPLE_SCALABLE_MALLOC
pfe_memory_zone = 0;
#else
pfem_term ();
#endif
free (pfe_compiler_state_ptr);
}
else if (pfe_operation == PFE_LOAD)
{
#if PFE_NO_THAW_LOAD
if ((unsigned)pfe_load_buffer_ptr == PFE_NO_THAW_LOAD_ADDR)
{
}
else
free (pfe_load_buffer_ptr);
#else
free (pfe_load_buffer_ptr);
#endif
pfe_load_buffer_ptr = 0;
}
else
{
}
pfe_operation = PFE_NOT_INITIALIZED;
pfe_freeze_thaw_ptr_fp = (pfe_freeze_thaw_ptr_t)NULL;
}
int
pfe_dump (the_file, the_freezer, the_header, the_header_size)
FILE *the_file;
void (*the_freezer) (void *);
void *the_header;
size_t the_header_size;
{
int range_idx, range_size, i;
long bytes_written;
int pad_bytes;
timevar_push (TV_PFE_WRITE);
if (pfe_operation != PFE_DUMP)
pfe_internal_error ("pfe_dump called when not initialized for dumping");
#if 0
printf ("include_hash hash table statistices:\n");
ht_dump_statistics (pfe_compiler_state_ptr->include_hash);
#endif
pfe_memory_locked_for_dump = 1;
#if USE_APPLE_SCALABLE_MALLOC
scalable_zone_find_ranges (pfe_memory_zone, pfe_add_dump_range);
#else
pfem_id_ranges (pfe_add_dump_range);
#endif
pfe_assign_dump_range_offsets (the_header_size);
#if PFE_NO_THAW_LOAD
if (pfe_dump_range_table [pfe_dump_range_table_nitems - 1].end_addr
< PFE_NO_THAW_LOAD_ADDR)
pfe_assumed_load_address = PFE_NO_THAW_LOAD_ADDR;
((pfe_compiler_state *)the_header)->pfe_assumed_load_address
= pfe_assumed_load_address;
#endif
if (the_freezer == 0)
pfe_internal_error ("pfe_dump: dump freezer function not specified");
if (the_header == 0)
pfe_internal_error ("pfe_dump: dump header not specified");
timevar_push (TV_PFE_FREEZE);
(*the_freezer) (the_header);
timevar_pop (TV_PFE_FREEZE);
#if PFE_DEBUG_MEMMGR_RANGES
printf ("\npfe_dump: writing header\n");
#endif
fwrite (the_header, the_header_size, 1, the_file);
bytes_written = the_header_size;
for (range_idx = 0; range_idx < pfe_dump_range_table_nitems; range_idx++)
{
pad_bytes = pfe_dump_range_table[range_idx].file_offset - bytes_written;
#if PFE_DEBUG_MEMMGR_RANGES
if (pad_bytes) printf ("pfe_dump: writing %d pad bytes\n", pad_bytes);
#endif
for (i = 0; i < pad_bytes; i++)
fputc (0, the_file);
bytes_written += pad_bytes;
#if PFE_DEBUG_MEMMGR_RANGES
printf ("pfe_dump: writing range %d: 0x%08X - 0x%08X [0x%08X]\n",
range_idx,
pfe_dump_range_table[range_idx].start_addr,
pfe_dump_range_table[range_idx].end_addr,
pfe_dump_range_table[range_idx].file_offset);
#endif
range_size = (pfe_dump_range_table[range_idx].end_addr
- pfe_dump_range_table[range_idx].start_addr);
fwrite ((char *)pfe_dump_range_table[range_idx].start_addr,
range_size, 1, the_file);
bytes_written += range_size;
}
pfe_memory_locked_for_dump = 0;
timevar_pop (TV_PFE_WRITE);
return 0;
}
int
pfe_dump_compiler_state (the_file)
FILE *the_file;
{
return pfe_dump (the_file, pfe_freeze_compiler_state,
pfe_compiler_state_ptr, sizeof (pfe_compiler_state));
}
void *
pfe_load (the_file)
FILE *the_file;
{
struct stat file_info;
if (pfe_operation != PFE_LOAD)
pfe_internal_error ("pfe_load called when not initialized for loading");
if (fstat (fileno (the_file), &file_info) != 0)
fatal_error ("PFE: unable to get file information for load file");
pfe_load_buffer_size = file_info.st_size;
#if PFE_NO_THAW_LOAD
{
#if PFE_NO_THAW_LOAD_USING_MMAP
caddr_t taddr;
taddr = (caddr_t)PFE_NO_THAW_LOAD_ADDR;
taddr = mmap (taddr,
pfe_load_buffer_size,
PROT_READ | PROT_WRITE,
MAP_FILE | MAP_FIXED | MAP_PRIVATE,
fileno (the_file),
(off_t)0);
if (taddr == (caddr_t)PFE_NO_THAW_LOAD_ADDR)
{
#if PFE_NO_THAW_LOAD_DIAGNOSTICS
printf ("pfe_load: mmap succeeded.\n");
#endif
pfe_load_buffer_ptr = (char *)PFE_NO_THAW_LOAD_ADDR;
}
else
{
#if PFE_NO_THAW_LOAD_DIAGNOSTICS
printf ("pfe_load: mmap failed (returned &d; errno = %d); "
"retrying using malloc.\n",
(int)taddr, errno);
#endif
pfe_load_buffer_ptr = (char *) xmalloc (pfe_load_buffer_size);
}
#else
int return_code;
unsigned int *taddr;
taddr = (unsigned int *)PFE_NO_THAW_LOAD_ADDR;
return_code = vm_allocate (mach_task_self (),
(vm_address_t *)&taddr,
pfe_load_buffer_size,
0);
if (return_code == KERN_SUCCESS)
pfe_load_buffer_ptr = (char *)PFE_NO_THAW_LOAD_ADDR;
else
{
#if PFE_NO_THAW_LOAD_DIAGNOSTICS
printf ("pfe_load: vm_allocate failed; retrying using malloc.\n");
#endif
pfe_load_buffer_ptr = (char *) xmalloc (pfe_load_buffer_size);
}
#endif
}
#else
pfe_load_buffer_ptr = (char *) xmalloc (pfe_load_buffer_size);
#endif
if (pfe_load_buffer_ptr == 0)
{
char msg[100];
sprintf (msg, "PFE: unable to allocate memory (%d bytes) for load file",
pfe_load_buffer_size);
fatal_error (msg);
}
#if PFE_NO_THAW_LOAD
#if PFE_NO_THAW_LOAD_USING_MMAP
#else
if ((fread (pfe_load_buffer_ptr, 1, pfe_load_buffer_size, the_file)
!= pfe_load_buffer_size))
fatal_io_error ("PFE: unable to read load file");
#endif
#else
if ((fread (pfe_load_buffer_ptr, 1, pfe_load_buffer_size, the_file)
!= pfe_load_buffer_size))
fatal_io_error ("PFE: unable to read load file");
#endif
return pfe_load_buffer_ptr;
}
void
pfe_load_compiler_state (the_file)
FILE *the_file;
{
timevar_push (TV_PFE_READ);
pfe_compiler_state_ptr = pfe_load (the_file);
timevar_pop (TV_PFE_READ);
#if PFE_NO_THAW_LOAD
pfe_assumed_load_address = pfe_compiler_state_ptr->pfe_assumed_load_address;
if (pfe_assumed_load_address != 0)
{
if ((unsigned)pfe_load_buffer_ptr == pfe_assumed_load_address)
pfe_no_thaw_load = 1;
else if ((unsigned)pfe_load_buffer_ptr + pfe_load_buffer_size
> PFE_NO_THAW_LOAD_ADDR)
fatal_error ("PFE: unable allocate load area at or below assumed load address");
else
pfe_load_offset_adjust = (unsigned)pfe_load_buffer_ptr
- pfe_assumed_load_address;
}
else
pfe_load_offset_adjust = (unsigned)pfe_load_buffer_ptr;
#endif
timevar_push (TV_PFE_THAW);
pfe_thaw_compiler_state (pfe_compiler_state_ptr);
timevar_pop (TV_PFE_THAW);
}
#if PFE_NO_THAW_LOAD
int
pfe_is_frozen (ptr)
void *ptr;
{
if (pfe_no_thaw_load)
return 0;
else if (pfe_assumed_load_address == 0)
return (unsigned)ptr & 1;
else
return (unsigned)ptr > PFE_NO_THAW_LOAD_ADDR;
}
#endif
int
pfe_is_pfe_mem (ptr)
void *ptr;
{
if (pfe_operation == PFE_DUMP)
{
#if USE_APPLE_SCALABLE_MALLOC
return scalable_zone_ptr_is_in_zone (pfe_memory_zone, ptr);
#else
return pfem_is_pfe_mem (ptr);
#endif
}
else if (pfe_operation == PFE_LOAD)
{
if (((unsigned)ptr >= (unsigned)pfe_load_buffer_ptr)
&& ((unsigned)ptr < (unsigned)(pfe_load_buffer_ptr
+ pfe_load_buffer_size)))
return 1;
else
return 0;
}
return 0;
}
void *
pfe_freeze_ptr (pp)
void *pp;
{
char *p;
unsigned long range_file_offset = 0;
unsigned long offset_in_range = 0;
p = *(char **)pp;
if (!p)
return NULL;
if (!PFE_IS_FROZEN(p))
{
#if PFE_MEMORY_STATS
pfe_freeze_ptrs++;
#endif
{
int lower_idx = 0;
int upper_idx = pfe_dump_range_table_nitems - 1;
int middle_idx;
while (lower_idx <= upper_idx)
{
middle_idx = (lower_idx + upper_idx) / 2;
if ((unsigned)p < pfe_dump_range_table[middle_idx].start_addr)
upper_idx = middle_idx - 1;
else if ((unsigned)p >= pfe_dump_range_table[middle_idx].end_addr
+ pfe_allowed_ptr_variance)
lower_idx = middle_idx + 1;
else
{
range_file_offset = pfe_dump_range_table[middle_idx].file_offset;
offset_in_range = (unsigned)p
- pfe_dump_range_table[middle_idx].start_addr;
break;
}
}
}
if ((range_file_offset == 0) && (offset_in_range == 0))
{
fprintf (stderr,
"pfe_freeze_ptr: 0x%08X @ 0x%08X is not a pointer to PFE memory.\n",
p, pp);
return (void *)p;
}
else
{
#if PFE_DEBUG_MEMMGR_RANGES && 0
printf ("pfe_freeze_ptr: 0x%08X @ 0x%08X -> 0x%08X\n", p, pp,
(range_file_offset + offset_in_range));
#endif
}
#if PFE_NO_THAW_LOAD
if (pfe_assumed_load_address == 0)
*(unsigned long *)pp = (range_file_offset + offset_in_range) | 1;
else
*(unsigned long *)pp = range_file_offset + offset_in_range
+ pfe_assumed_load_address;
#else
*(unsigned long *)pp = (range_file_offset + offset_in_range) | 1;
#endif
}
else
{
#if PFE_DEBUG_MEMMGR_RANGES
printf ("pfe_freeze_ptr: 0x%08X @ 0x%08X already frozen\n", p, pp);
#endif
}
return (void *)p;
}
void *
pfe_thaw_ptr (pp)
void *pp;
{
unsigned long offset;
#if PFE_DEBUG_EXTRA_CHECKING
if ((pfe_extra_checking)
&& (((unsigned)pp < (unsigned)pfe_load_buffer_ptr)
|| ((unsigned)pp
>= (unsigned)(pfe_load_buffer_ptr
+ pfe_load_buffer_size
+ pfe_allowed_ptr_variance)))
&& (pp != pfe_temp_ptr))
fprintf (stderr,
"pfe_thaw_ptr: trying to thaw a pointer @ 0x%08X that"
" is not in the load file.\n",
pp);
#endif
#if PFE_NO_THAW_LOAD
if (pfe_no_thaw_load)
return *(void **)pp;
#endif
offset = *(unsigned long *)pp;
if (PFE_IS_FROZEN ((void *)offset))
{
#if PFE_MEMORY_STATS
pfe_thaw_ptrs++;
#endif
#if PFE_DEBUG_EXTRA_CHECKING
#if PFE_NO_THAW_LOAD
if (pfe_extra_checking
&& (offset - pfe_assumed_load_address)
> (pfe_load_buffer_size + pfe_allowed_ptr_variance))
#else
if (pfe_extra_checking
&& (offset & 0xFFFFFFFE) > (pfe_load_buffer_size
+ pfe_allowed_ptr_variance))
#endif
fprintf (stderr,
"pfe_thaw_ptr: 0x%08X @ 0x%08X is not a pointer to PFE memory.\n",
offset & 0xFFFFFFFE, pp);
#endif
#if PFE_NO_THAW_LOAD
*(void **)pp = (void *)((offset & 0xFFFFFFFE)
+ pfe_load_offset_adjust);
#else
*(void **)pp = (void *)((unsigned)pfe_load_buffer_ptr
+ (offset & 0xFFFFFFFE));
#endif
}
return *(void **)pp;
}
void *
pfe_freeze_thaw_ptr (pp)
void **pp;
{
void *p;
if (pfe_operation == PFE_DUMP)
{
p = *pp;
if (p == NULL || PFE_IS_FROZEN (p))
return NULL;
pfe_freeze_ptr (pp);
}
else
{
if (!PFE_IS_FROZEN ((void *)(*(unsigned long *)pp)))
return NULL;
p = pfe_thaw_ptr (pp);
}
return p;
}
void *
pfe_freeze_thaw_ptr_with_variance (pp, n)
void **pp;
unsigned long n;
{
void *p;
pfe_allowed_ptr_variance = n;
if (pfe_operation == PFE_DUMP)
{
p = *pp;
if (p == NULL || PFE_IS_FROZEN (p))
return NULL;
pfe_freeze_ptr (pp);
}
else
{
if (!PFE_IS_FROZEN ((void *)(*(unsigned long *)pp)))
return NULL;
p = pfe_thaw_ptr (pp);
}
pfe_allowed_ptr_variance = 0;
return p;
}
void *
pfe_real_ptr (p)
void *p;
{
unsigned long offset;
if (pfe_operation == PFE_DUMP)
{
if (PFE_IS_FROZEN (p))
{
int lower_idx = 0;
int upper_idx = pfe_dump_range_table_nitems - 1;
int middle_idx;
#if PFE_NO_THAW_LOAD
if (pfe_assumed_load_address)
offset = (unsigned)p - pfe_assumed_load_address;
else
#endif
offset = (unsigned)p & 0xFFFFFFFE;
while (lower_idx <= upper_idx)
{
middle_idx = (lower_idx + upper_idx) / 2;
if (offset < pfe_dump_range_table[middle_idx].file_offset)
upper_idx = middle_idx - 1;
else if (offset >= (pfe_dump_range_table[middle_idx].end_addr
- pfe_dump_range_table[middle_idx].start_addr
+ pfe_dump_range_table[middle_idx].file_offset))
lower_idx = middle_idx + 1;
else
return (void *)(offset
- pfe_dump_range_table[middle_idx].file_offset
+ pfe_dump_range_table[middle_idx].start_addr);
}
pfe_internal_error ("pfe_real_ptr could not thaw frozen ptr");
}
}
else if (pfe_operation == PFE_LOAD)
{
if (PFE_IS_FROZEN (p))
{
offset = (unsigned)p & 0xFFFFFFFE;
#if PFE_NO_THAW_LOAD
return (void *)((unsigned)pfe_load_offset_adjust + offset);
#else
return (void *)((unsigned)pfe_load_buffer_ptr + offset);
#endif
}
}
return p;
}
void
pfe_using_temp_ptr (p)
void **p;
{
pfe_temp_ptr = p;
}
void *
pfe_malloc (size)
size_t size;
{
void *p;
#if PFE_MEMORY_STATS
pfe_malloc_total_size += size;
pfe_mallocs++;
#endif
if (pfe_operation == PFE_DUMP)
{
#if PFE_DEBUG_EXTRA_CHECKING
if (pfe_memory_locked_for_dump)
pfe_internal_error ("pfe_malloc: allocation routine called "
"when freezing");
#endif
#if USE_APPLE_SCALABLE_MALLOC
p = pfe_memory_zone->really_call_malloc (pfe_memory_zone, size);
#if 0
printf ("pfe_malloc: 0x%08X size %d\n", p, size);
#endif
#else
p = pfem_malloc (size);
#endif
if (!p)
fatal_error ("PFE: memory exhausted");
}
else
p = xmalloc (size);
return p;
}
void *
pfe_calloc (nobj, size)
size_t nobj;
size_t size;
{
void *p;
#if PFE_MEMORY_STATS
pfe_malloc_total_size += (size * nobj);
pfe_callocs++;
#endif
if (pfe_operation == PFE_DUMP)
{
#if PFE_DEBUG_EXTRA_CHECKING
if (pfe_memory_locked_for_dump)
pfe_internal_error ("pfe_calloc: allocation routine called "
"when freezing");
#endif
#if USE_APPLE_SCALABLE_MALLOC
p = pfe_memory_zone->really_call_calloc (pfe_memory_zone, nobj, size);
#else
p = pfem_calloc (nobj, size);
#endif
if (!p)
fatal_error ("PFE: memory exhausted");
}
else
p = xcalloc (nobj, size);
return p;
}
void *
pfe_realloc (p, size)
void *p;
size_t size;
{
#if PFE_MEMORY_STATS
pfe_malloc_total_size += size;
pfe_reallocs++;
#endif
if (pfe_operation == PFE_DUMP)
{
#if PFE_DEBUG_EXTRA_CHECKING
if (pfe_memory_locked_for_dump)
pfe_internal_error ("pfe_realloc: allocation routine called "
"when freezing");
#endif
#if USE_APPLE_SCALABLE_MALLOC
p = pfe_memory_zone->really_call_realloc (pfe_memory_zone, p, size);
#else
p = pfem_realloc (p, size);
#endif
if (!p)
fatal_error ("PFE: memory exhausted");
}
else if (pfe_operation == PFE_LOAD && pfe_is_pfe_mem (p))
{
char *newp;
#if PFE_DEBUG_EXTRA_CHECKING && 0
printf ("pfe_realloc: realloc from PFE memory: 0x%08X; "
"new size %d\n", p, size);
#endif
newp = xmalloc (size);
if (((unsigned)p + size) > ((unsigned)pfe_load_buffer_ptr
+ pfe_load_buffer_size))
p = memcpy (newp, p, (size_t)((unsigned)pfe_load_buffer_ptr
+ pfe_load_buffer_size
- (unsigned)p));
else
p = memcpy (newp, p, size);
}
else
p = xrealloc (p, size);
return p;
}
void
pfe_free (ptr)
void *ptr;
{
if (!ptr) return;
#if PFE_MEMORY_STATS
pfe_frees++;
#endif
if (pfe_operation == PFE_DUMP)
{
#if USE_APPLE_SCALABLE_MALLOC
pfe_memory_zone->free (pfe_memory_zone, ptr);
#else
pfem_free (ptr);
#endif
}
else if (pfe_operation == PFE_LOAD)
{
if (((unsigned)ptr < (unsigned)pfe_load_buffer_ptr)
|| ((unsigned)ptr >= ((unsigned)pfe_load_buffer_ptr
+ pfe_load_buffer_size)))
free (ptr);
#if PFE_MEMORY_STATS
else
pfe_frees_from_load_area++;
#endif
}
else
{
free (ptr);
}
}
#if PFE_MALLOC_STATS
void
pfe_s_track_mallocs (size, kind)
size_t size;
enum pfe_alloc_object_kinds kind;
{
int lower_idx, upper_idx, middle_idx, new_entry_sorts_higher;
if (pfe_s_malloc_table_nitems >= pfe_s_malloc_table_size)
{
pfe_s_malloc_table_size += PFE_S_MALLOC_TABLE_INCR;
pfe_s_malloc_table = (pfe_s_malloc_entry *)
xrealloc (pfe_s_malloc_table,
sizeof (pfe_s_malloc_entry)
* pfe_s_malloc_table_size);
}
if (pfe_s_malloc_table_nitems == 0)
middle_idx = 0;
else
{
lower_idx = 0;
upper_idx = pfe_s_malloc_table_nitems - 1;
while (lower_idx <= upper_idx)
{
new_entry_sorts_higher = 0;
middle_idx = (lower_idx + upper_idx) / 2;
if (kind < pfe_s_malloc_table[middle_idx].kind)
upper_idx = middle_idx - 1;
else if (kind > pfe_s_malloc_table[middle_idx].kind)
{
lower_idx = middle_idx + 1;
new_entry_sorts_higher = 1;
}
else
{
if (size < pfe_s_malloc_table[middle_idx].size)
upper_idx = middle_idx - 1;
else if (size > pfe_s_malloc_table[middle_idx].size)
{
lower_idx = middle_idx + 1;
new_entry_sorts_higher = 1;
}
else
{
pfe_s_malloc_table[middle_idx].count++;
return;
}
}
}
if (new_entry_sorts_higher)
middle_idx++;
if (middle_idx < pfe_s_malloc_table_nitems)
memcpy (&pfe_s_malloc_table[middle_idx + 1],
&pfe_s_malloc_table[middle_idx],
sizeof (pfe_s_malloc_entry)
* (pfe_s_malloc_table_nitems - middle_idx));
}
pfe_s_malloc_table[middle_idx].size = size;
pfe_s_malloc_table[middle_idx].kind = kind;
pfe_s_malloc_table[middle_idx].count = 1;
pfe_s_malloc_table_nitems++;
}
void *
pfe_s_malloc (size, kind)
size_t size;
enum pfe_alloc_object_kinds kind;
{
if (pfe_display_memory_stats)
pfe_s_track_mallocs (size, kind);
return pfe_malloc (size);
}
void *
pfe_s_calloc (nobj, size, kind)
size_t nobj;
size_t size;
enum pfe_alloc_object_kinds kind;
{
if (pfe_display_memory_stats)
pfe_s_track_mallocs (nobj * size, kind);
return pfe_calloc (nobj, size);
}
void *
pfe_s_realloc (p, size, kind)
void *p;
size_t size;
enum pfe_alloc_object_kinds kind;
{
if (pfe_display_memory_stats)
pfe_s_track_mallocs (size, kind);
return pfe_realloc (p, size);
}
static void
pfe_s_display_malloc_stats(void)
{
int idx;
printf ("\nPFE malloc usage statistics:\n");
for (idx = 0; idx < pfe_s_malloc_table_nitems; idx++)
printf ("%-30s: size(%6d): count(%5d)\n",
pfe_alloc_object_kinds_names[pfe_s_malloc_table[idx].kind],
pfe_s_malloc_table[idx].size,
pfe_s_malloc_table[idx].count);
}
#endif
static hashnode
pfe_alloc_str_node (table)
hash_table *table ATTRIBUTE_UNUSED;
{
return xmalloc (sizeof (hashnode));
}
static hashnode
pfe_alloc_include_hash_node (table)
hash_table *table ATTRIBUTE_UNUSED;
{
return (hashnode) pfe_malloc (sizeof (pfe_include_header));
}
void *
pfe_savestring (s)
char *s;
{
if (!s)
return NULL;
if (pfe_operation == PFE_DUMP)
{
hashnode ht_node = ht_lookup (pfe_str_hash_table,
(const unsigned char *) s,
strlen (s), HT_ALLOC);
#if PFE_MEMORY_STATS
pfe_savestrings++;
#endif
return (void *)ht_node->str;
}
else
return s;
}
static void
pfe_add_dump_range (start_addr, end_addr)
unsigned long start_addr;
unsigned long end_addr;
{
int range_idx;
#if PFE_DEBUG_MEMMGR_RANGES
printf ("pfe_add_dump_range: @0x%08X - 0x%08X\n", start_addr, end_addr);
#endif
if (pfe_dump_range_table_nitems >= pfe_dump_range_table_size)
{
pfe_dump_range_table_size += PFE_DUMP_RANGE_TABLE_INCR;
pfe_dump_range_table = (pfe_dump_memory_range *)
xrealloc (pfe_dump_range_table,
sizeof (pfe_dump_memory_range)
* pfe_dump_range_table_size);
}
for (range_idx = 0; range_idx < pfe_dump_range_table_nitems; range_idx++)
if (start_addr < pfe_dump_range_table[range_idx].start_addr)
{
memcpy (&pfe_dump_range_table[range_idx + 1],
&pfe_dump_range_table[range_idx],
sizeof (pfe_dump_memory_range)
* (pfe_dump_range_table_nitems - range_idx));
break;
}
pfe_dump_range_table[range_idx].start_addr = start_addr;
pfe_dump_range_table[range_idx].end_addr = end_addr;
pfe_dump_range_table_nitems++;
}
static void
pfe_assign_dump_range_offsets (int header_size)
{
int range_idx;
long dump_file_offset = header_size;
for (range_idx = 0; range_idx < pfe_dump_range_table_nitems; range_idx++)
{
#if 0
dump_file_offset = (dump_file_offset + 4095) & 0xFFFFF000;
#else
dump_file_offset = (dump_file_offset + 15) & 0xFFFFFFF0;
#endif
pfe_dump_range_table[range_idx].file_offset = dump_file_offset;
dump_file_offset += (pfe_dump_range_table[range_idx].end_addr
- pfe_dump_range_table[range_idx].start_addr);
}
#if PFE_MEMORY_STATS
pfe_load_buffer_size = dump_file_offset;
#endif
}