/* Copy of one of the input file's ehdr. */
static GElf_Ehdr multi_ehdr;
+static int multi_ptr_size;
+static int multi_endian;
+
/* True while in write_multifile. */
-static bool do_multifile;
+static bool wr_multifile;
+
+/* True while in optimize_multifile. */
+static bool op_multifile;
/* Filename if inter-file size optimization should be performed. */
static const char *multifile;
{
unsigned long ret = die->die_size;
dw_die_ref child;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return 0;
for (child = die->die_child; child; child = child->die_sib)
ret += calc_sizes (child);
return;
if (strp_htab == NULL)
{
+ if (multifile == NULL)
+ return;
strp_htab = htab_try_create (50, strp_hash, strp_eq, NULL);
if (strp_htab == NULL)
dwz_oom ();
for each CU in it construct internal represetnation for the CU
and its DIE tree, compute checksums of DIEs and look for duplicates. */
static int
-read_debug_info (DSO *dso)
+read_debug_info (DSO *dso, bool note_strp_forms)
{
unsigned char *ptr, *endcu, *endsec;
unsigned int value;
&& (die->die_parent->die_parent == NULL
|| die->die_parent->die_named_namespace))
die->die_named_namespace = 1;
- if (multifile)
+ if (note_strp_forms)
note_strp_offset (read_32 (ptr));
else
ptr += 4;
die->u.p2.die_new_offset = 0;
die->u.p2.die_intracu_udata_size = 0;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return 0;
t->entry = 0;
t->tag = die->die_tag;
else
{
ref = die;
- if (do_multifile
+ if (wr_multifile
&& (die->die_parent == NULL || die->die_named_namespace))
origin = die;
}
if (die->die_child && die->die_sib)
for (sib = die->die_sib; sib; sib = sib->die_sib)
- if (do_multifile ? !sib->die_no_multifile : !sib->die_remove)
+ if (wr_multifile ? !sib->die_no_multifile : !sib->die_remove)
break;
if (ref != NULL && origin == NULL)
{
read_uleb128 (ptr);
/* No longer count the abbrev uleb128 size in die_size.
We'll add it back after determining the new abbrevs. */
- if (do_multifile)
+ if (wr_multifile)
i = -1U;
else
for (i = 0; i < reft->nattr; i++)
while (form == DW_FORM_indirect)
form = read_uleb128 (ptr);
- if (do_multifile
+ if (wr_multifile
&& (reft->attr[i].attr == DW_AT_decl_file
|| reft->attr[i].attr == DW_AT_call_file))
{
dw_die_ref child;
unsigned int i;
struct abbrev_tag *t = die->u.p2.die_new_abbrev;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return off;
die->u.p2.die_new_offset = off;
die->die_size += size_of_uleb128 (die->u.p2.die_new_abbrev->entry);
dw_die_ref **intracuvec)
{
dw_die_ref child;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return off;
assert (off <= die->u.p2.die_new_offset);
die->u.p2.die_new_offset = off;
unsigned int intracusize, dw_die_ref **intracuvec)
{
dw_die_ref child;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return off;
die->u.p2.die_new_offset = off;
/* As we aren't adjusting sizes of exprloc, if in the new layout
beginning of the CU and we try to preserve that, so this shouldn't
trigger for GCC generated code. */
if (die->die_op_type_referenced
- && !do_multifile
+ && !wr_multifile
&& size_of_uleb128 (off)
> size_of_uleb128 (die->die_offset - die->die_cu->cu_offset))
return -1U;
struct abbrev_tag *t;
unsigned int ncus, nlargeabbrevs = 0, i, laststart;
unsigned char *to_free = obstack_alloc (&alt_ob, 1);
+ bool saw_cu_normal = false;
t = (struct abbrev_tag *)
obstack_alloc (&alt_ob,
unsigned int limit, uleb128_size;
for (child = cu->cu_die->die_child; child; child = child->die_sib)
- if (child->die_op_type_referenced && !do_multifile)
+ if (child->die_op_type_referenced && !wr_multifile)
{
child->u.p2.die_new_abbrev->op_type_referenced = 1;
/* If the old offset was close to uleb128 boundary, ensure
}
obstack_free (&ob, (void *) arr);
obstack_free (&alt_ob, (void *) intracuarr);
- cu->cu_new_offset = (do_multifile ? multi_info_off : 0) + total_size;
+ if (wr_multifile && cu->cu_kind == CU_NORMAL && !saw_cu_normal)
+ {
+ total_size += 11;
+ saw_cu_normal = true;
+ }
+ cu->cu_new_offset = (wr_multifile ? multi_info_off : 0) + total_size;
total_size += cusize;
}
+ if (wr_multifile)
+ total_size += saw_cu_normal ? 11 : 22;
obstack_free (&alt_ob, (void *) t);
cuarr = (struct dw_cu **) obstack_alloc (&alt_ob,
ncus * sizeof (struct dw_cu *));
continue;
}
cu->u2.cu_new_abbrev_offset
- = (do_multifile ? multi_abbrev_off : 0) + abbrev_size;
+ = (wr_multifile ? multi_abbrev_off : 0) + abbrev_size;
nabbrevs = htab_elements (cu->cu_new_abbrev);
htab_traverse (cu->cu_new_abbrev, list_abbrevs, &ob);
assert (obstack_object_size (&ob) == nabbrevs * sizeof (void *));
dw_die_ref child, sib = NULL, origin = NULL;
struct abbrev_tag *t;
- if (do_multifile ? die->die_no_multifile : die->die_remove)
+ if (wr_multifile ? die->die_no_multifile : die->die_remove)
return ptr;
if (die->die_offset == -1U)
{
else
{
ref = die;
- if (do_multifile
+ if (wr_multifile
&& (die->die_parent == NULL || die->die_named_namespace))
origin = die;
}
if (die->die_child && die->die_sib)
for (sib = die->die_sib; sib; sib = sib->die_sib)
- if (do_multifile ? !sib->die_no_multifile : !sib->die_remove)
+ if (wr_multifile ? !sib->die_no_multifile : !sib->die_remove)
break;
t = die->u.p2.die_new_abbrev;
write_uleb128 (ptr, t->entry);
while (form == DW_FORM_indirect)
form = read_uleb128 (inptr);
- if (do_multifile
+ if (wr_multifile
&& (reft->attr[i].attr == DW_AT_decl_file
|| reft->attr[i].attr == DW_AT_call_file))
{
read_uleb128 (inptr);
break;
case DW_FORM_strp:
- if (do_multifile)
+ if (wr_multifile)
{
unsigned int strp = lookup_strp_offset (read_32 (inptr));
memcpy (ptr, orig_ptr, inptr - 4 - orig_ptr);
unsigned char *p = get_AT (origin, DW_AT_stmt_list, &form);
assert (p && (form == DW_FORM_sec_offset
|| form == DW_FORM_data4));
- if (do_multifile)
+ if (wr_multifile)
write_32 (ptr, multi_line_off);
else
{
struct dw_cu *cu;
unsigned char *info = malloc (debug_sections[DEBUG_INFO].new_size);
unsigned char *ptr = info;
+ bool saw_cu_normal = false;
if (info == NULL)
dwz_oom ();
/* Ignore .debug_types CUs. */
if (cu->cu_kind == CU_TYPES)
break;
+ if (wr_multifile && !saw_cu_normal && cu->cu_kind == CU_NORMAL)
+ {
+ /* Emit a barrier separating CU_PUs from CU_NORMAL. */
+ write_32 (ptr, 7);
+ write_16 (ptr, 2);
+ write_32 (ptr, 0);
+ write_8 (ptr, ptr_size);
+ saw_cu_normal = true;
+ }
if (cu->cu_next && cu->cu_next->cu_kind != CU_TYPES)
- next_off = cu->cu_next->cu_new_offset;
- else if (do_multifile)
- next_off += multi_info_off;
+ {
+ next_off = cu->cu_next->cu_new_offset;
+ if (wr_multifile && !saw_cu_normal
+ && cu->cu_next->cu_kind == CU_NORMAL)
+ next_off -= 11L;
+ }
+ else if (wr_multifile)
+ next_off += multi_info_off - (saw_cu_normal ? 11L : 22L);
/* Write CU header. */
write_32 (ptr, next_off - cu->cu_new_offset - 4);
write_16 (ptr, cu->cu_version);
write_32 (ptr, cu->u2.cu_new_abbrev_offset);
write_8 (ptr, ptr_size);
ptr = write_die (ptr, cu->cu_die, NULL);
- assert (info + (next_off - (do_multifile ? multi_info_off : 0)) == ptr);
+ assert (info + (next_off - (wr_multifile ? multi_info_off : 0)) == ptr);
+ }
+ if (wr_multifile)
+ {
+ unsigned int i;
+ /* And terminate the contribution by the current object file. */
+ for (i = 0; i < (saw_cu_normal ? 1 : 2); i++)
+ {
+ write_32 (ptr, 7);
+ write_16 (ptr, 2);
+ write_32 (ptr, 0);
+ write_8 (ptr, ptr_size);
+ }
}
assert (info + debug_sections[DEBUG_INFO].new_size == ptr);
}
Elf_Scn *scn;
int i, j;
- for (i = 0; debug_sections[i].name; ++i)
- {
- debug_sections[i].data = NULL;
- debug_sections[i].size = 0;
- debug_sections[i].new_data = NULL;
- debug_sections[i].new_size = 0;
- debug_sections[i].sec = 0;
- }
- ptr_size = 0;
-
for (i = 1; i < dso->ehdr.e_shnum; ++i)
if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))
&& dso->shdr[i].sh_size)
return 1;
}
- if (read_debug_info (dso))
+ if (read_debug_info (dso, multifile != NULL))
return 1;
return 0;
do_write_32 = NULL;
do_write_64 = NULL;
edge_freelist = NULL;
- do_multifile = false;
+ wr_multifile = false;
max_strp_off = 0;
max_line_id = 0;
}
filetbllen += size_of_uleb128 (filearr[i]->file->time);
filetbllen += size_of_uleb128 (filearr[i]->file->size);
}
+ dirarr = (unsigned int *) obstack_finish (&ob);
}
len = 17 + filetbllen + dirtbllen;
bool any_cus = false;
unsigned int i;
int ret = 0;
+
+ if ((multi_ptr_size && ptr_size != multi_ptr_size)
+ || (multi_endian
+ && multi_endian != (do_read_32 == buf_read_ule32
+ ? ELFDATA2LSB : ELFDATA2MSB)))
+ {
+ error (0, 0, "Multi-file optimization not allowed for different"
+ "pointer sizes or endianity");
+ multifile = NULL;
+ return 1;
+ }
+ multi_ptr_size = ptr_size;
+ multi_endian = do_read_32 == buf_read_ule32 ? ELFDATA2LSB : ELFDATA2MSB;
+
for (i = 0; debug_sections[i].name; i++)
{
saved_new_data[i] = debug_sections[i].new_data;
else
*cup = (*cup)->cu_next;
*cup = NULL;
- do_multifile = true;
+ wr_multifile = true;
if (compute_abbrevs (NULL))
ret = 1;
else if ((unsigned int) (multi_info_off
}
}
}
- do_multifile = false;
+ wr_multifile = false;
for (i = 0; debug_sections[i].name; i++)
{
free (debug_sections[i].new_data);
static int
optimize_multifile (void)
{
+ DSO dsobuf, *dso;
int fd = -1;
unsigned int i;
Elf *elf = NULL;
= "\0.shstrtab\0.debug_info\0.debug_abbrev\0.debug_line\0.debug_str";
const char *p;
- if (multi_ehdr.e_ident[0] == '\0')
+ if (multi_ehdr.e_ident[0] == '\0'
+ || multi_ptr_size == 0
+ || multi_endian == 0)
return 1;
if ((multi_line_off == 0 && write_multifile_line ()))
{
error (0, 0, "Error mmapping multi-file temporary files");
fail:
+ op_multifile = false;
+ cleanup ();
if (elf)
elf_end (elf);
if (fd != -1)
return 1;
}
+ if (multi_endian == ELFDATA2LSB)
+ {
+ do_read_16 = buf_read_ule16;
+ do_read_32 = buf_read_ule32;
+ do_read_64 = buf_read_ule64;
+ do_write_16 = buf_write_le16;
+ do_write_32 = buf_write_le32;
+ do_write_64 = buf_write_le64;
+ }
+ else if (multi_endian == ELFDATA2MSB)
+ {
+ do_read_16 = buf_read_ube16;
+ do_read_32 = buf_read_ube32;
+ do_read_64 = buf_read_ube64;
+ do_write_16 = buf_write_be16;
+ do_write_32 = buf_write_be32;
+ do_write_64 = buf_write_be64;
+ }
+ else
+ abort ();
+ ptr_size = multi_ptr_size;
+ memset (&dsobuf, '\0', sizeof (dsobuf));
+ dso = &dsobuf;
+ dso->filename = multifile;
+ op_multifile = true;
+
+ obstack_alloc_failed_handler = dwz_oom;
+ if (setjmp (oom_buf))
+ {
+ error (0, ENOMEM, "%s: Could not allocate memory", dso->filename);
+ op_multifile = false;
+ goto fail;
+ }
+ else
+ {
+ obstack_init (&ob);
+ obstack_init (&alt_ob);
+
+ if (0 && read_debug_info (dso, false))
+ goto fail;
+ }
+
+ op_multifile = false;
+ cleanup ();
fd = open (multifile, O_RDWR | O_CREAT, 0600);
if (fd < 0)
{
for (i = 0; debug_sections[i].name; i++)
if (debug_sections[i].size)
{
- multi_ehdr.e_shoff += debug_sections[i].size;
- multi_ehdr.e_shnum++;
+ multi_ehdr.e_shoff += debug_sections[i].size;
+ multi_ehdr.e_shnum++;
}
multi_ehdr.e_shstrndx = multi_ehdr.e_shnum - 1;