X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fvms-alpha.c;h=32f4e68bbba8ab954469cbb8824c324e449c53a8;hb=b50ef514ff0c8d5506227c412c508f9f538bcf5a;hp=69822a2ce6a4c379e3c2b5c555846de0aa84a695;hpb=cb7f4b298e5e0a3ab4fb6b13aa89e970478597bc;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index 69822a2ce6..32f4e68bbb 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -1,5 +1,5 @@ /* vms.c -- BFD back-end for EVAX (openVMS/Alpha) files. - Copyright (C) 1996-2019 Free Software Foundation, Inc. + Copyright (C) 1996-2020 Free Software Foundation, Inc. Initial version written by Klaus Kaempf (kkaempf@rmi.de) Major rewrite by Adacore. @@ -529,12 +529,12 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) asection *section; flagword bfd_flags; - /* PR 17512: file: 3d9e9fe9. - 12 is the offset of the eisdsize field from the start of the record (8) - plus the size of the eisdsize field (4). */ - if (offset >= PRIV (recrd.rec_size) - 12) + /* PR 17512: file: 3d9e9fe9. */ + if (offset > PRIV (recrd.rec_size) + || (PRIV (recrd.rec_size) - offset + < offsetof (struct vms_eisd, eisdsize) + 4)) return FALSE; - eisd = (struct vms_eisd *)(PRIV (recrd.rec) + offset); + eisd = (struct vms_eisd *) (PRIV (recrd.rec) + offset); rec_size = bfd_getl32 (eisd->eisdsize); if (rec_size == 0) break; @@ -547,11 +547,10 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) } /* Make sure that there is enough data present in the record. */ - /* FIXME: Should we use sizeof (struct vms_eisd) rather than just 32 here ? */ - if (rec_size < 32) + if (rec_size < offsetof (struct vms_eisd, type) + 1) return FALSE; /* Make sure that the record is not too big either. */ - if (offset + rec_size >= PRIV (recrd.rec_size)) + if (rec_size > PRIV (recrd.rec_size) - offset) return FALSE; offset += rec_size; @@ -592,13 +591,16 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) if (flags & EISD__M_GBL) { - if (rec_size < offsetof (struct vms_eisd, gblnam)) + if (rec_size <= offsetof (struct vms_eisd, gblnam)) return FALSE; else if (rec_size < sizeof (struct vms_eisd)) - name = _bfd_vms_save_counted_string (eisd->gblnam, + name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, rec_size - offsetof (struct vms_eisd, gblnam)); else - name = _bfd_vms_save_counted_string (eisd->gblnam, EISD__K_GBLNAMLEN); + name = _bfd_vms_save_counted_string (abfd, eisd->gblnam, + EISD__K_GBLNAMLEN); + if (name == NULL || name[0] == 0) + return FALSE; bfd_flags |= SEC_COFF_SHARED_LIBRARY; bfd_flags &= ~(SEC_ALLOC | SEC_LOAD); } @@ -610,7 +612,9 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) { const char *pfx; - name = (char*) bfd_alloc (abfd, 32); + name = (char *) bfd_alloc (abfd, 32); + if (name == NULL) + return FALSE; if (flags & EISD__M_DZRO) pfx = "BSS"; else if (flags & EISD__M_EXE) @@ -632,7 +636,7 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) section->size = size; section->vma = vaddr; - if (!bfd_set_section_flags (abfd, section, bfd_flags)) + if (!bfd_set_section_flags (section, bfd_flags)) return FALSE; } @@ -687,7 +691,7 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) section->size = dstsize; section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1); - if (!bfd_set_section_flags (abfd, section, bfd_flags)) + if (!bfd_set_section_flags (section, bfd_flags)) return FALSE; PRIV (dst_section) = section; @@ -705,7 +709,7 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) section->size = dmtbytes; section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1); - if (!bfd_set_section_flags (abfd, section, bfd_flags)) + if (!bfd_set_section_flags (section, bfd_flags)) return FALSE; } @@ -924,36 +928,39 @@ _bfd_vms_slurp_ehdr (bfd *abfd) PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); if ((vms_rec + 20 + vms_rec[20] + 1) >= end) goto fail; - PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20, vms_rec[20]); + PRIV (hdr_data).hdr_t_name + = _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]); ptr = vms_rec + 20 + vms_rec[20] + 1; if ((ptr + *ptr + 1) >= end) goto fail; - PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr, *ptr); + PRIV (hdr_data).hdr_t_version + = _bfd_vms_save_counted_string (abfd, ptr, *ptr); ptr += *ptr + 1; if (ptr + 17 >= end) goto fail; - PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17); + PRIV (hdr_data).hdr_t_date + = _bfd_vms_save_sized_string (abfd, ptr, 17); break; case EMH__C_LNM: if (vms_rec + PRIV (recrd.rec_size - 6) > end) goto fail; - PRIV (hdr_data).hdr_c_lnm = - _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); + PRIV (hdr_data).hdr_c_lnm + = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); break; case EMH__C_SRC: if (vms_rec + PRIV (recrd.rec_size - 6) > end) goto fail; - PRIV (hdr_data).hdr_c_src = - _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); + PRIV (hdr_data).hdr_c_src + = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); break; case EMH__C_TTL: if (vms_rec + PRIV (recrd.rec_size - 6) > end) goto fail; - PRIV (hdr_data).hdr_c_ttl = - _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); + PRIV (hdr_data).hdr_c_ttl + = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6)); break; case EMH__C_CPR: @@ -1137,12 +1144,20 @@ add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym) Return NULL in case of error. */ static struct vms_symbol_entry * -add_symbol (bfd *abfd, const unsigned char *ascic) +add_symbol (bfd *abfd, const unsigned char *ascic, unsigned int max) { struct vms_symbol_entry *entry; - int len; + unsigned int len; len = *ascic++; + max -= 1; + if (len > max) + { + _bfd_error_handler (_("record is too small for symbol name length")); + bfd_set_error (bfd_error_bad_value); + return NULL; + } + entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len); if (entry == NULL) return NULL; @@ -1164,7 +1179,8 @@ _bfd_vms_slurp_egsd (bfd *abfd) int gsd_type; unsigned int gsd_size; unsigned char *vms_rec; - unsigned long base_addr; + bfd_vma base_addr; + long psindx; vms_debug2 ((2, "EGSD\n")); @@ -1180,7 +1196,7 @@ _bfd_vms_slurp_egsd (bfd *abfd) PRIV (recrd.rec_size) -= 8; /* Calculate base address for each section. */ - base_addr = 0L; + base_addr = 0; while (PRIV (recrd.rec_size) > 4) { @@ -1194,16 +1210,19 @@ _bfd_vms_slurp_egsd (bfd *abfd) /* PR 21615: Check for size overflow. */ if (PRIV (recrd.rec_size) < gsd_size) { - _bfd_error_handler (_("corrupt EGSD record: size (%#x) is larger than remaining space (%#x)"), - gsd_size, PRIV (recrd.rec_size)); + _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " + "is larger than remaining space (%#x)"), + gsd_type, gsd_size, PRIV (recrd.rec_size)); bfd_set_error (bfd_error_bad_value); return FALSE; } if (gsd_size < 4) { - _bfd_error_handler (_("corrupt EGSD record: size (%#x) is too small"), - gsd_size); + too_small: + _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) " + "is too small"), + gsd_type, gsd_size); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -1213,10 +1232,12 @@ _bfd_vms_slurp_egsd (bfd *abfd) case EGSD__C_PSC: /* Program section definition. */ { - struct vms_egps *egps = (struct vms_egps *)vms_rec; + struct vms_egps *egps = (struct vms_egps *) vms_rec; flagword new_flags, vms_flags; asection *section; + if (offsetof (struct vms_egps, flags) + 2 > gsd_size) + goto too_small; vms_flags = bfd_getl16 (egps->flags); if ((vms_flags & EGPS__V_REL) == 0) @@ -1228,9 +1249,15 @@ _bfd_vms_slurp_egsd (bfd *abfd) else { char *name; - unsigned long align_addr; - - name = _bfd_vms_save_counted_string (&egps->namlng, gsd_size - 4); + bfd_vma align_addr; + size_t left; + + if (offsetof (struct vms_egps, namlng) >= gsd_size) + goto too_small; + left = gsd_size - offsetof (struct vms_egps, namlng); + name = _bfd_vms_save_counted_string (abfd, &egps->namlng, left); + if (name == NULL || name[0] == 0) + return FALSE; section = bfd_make_section (abfd, name); if (!section) @@ -1238,12 +1265,13 @@ _bfd_vms_slurp_egsd (bfd *abfd) section->filepos = 0; section->size = bfd_getl32 (egps->alloc); - section->alignment_power = egps->align; + section->alignment_power = egps->align & 31; vms_section_data (section)->flags = vms_flags; vms_section_data (section)->no_flags = 0; - new_flags = vms_secflag_by_name (evax_section_flags, name, + new_flags = vms_secflag_by_name (evax_section_flags, + section->name, section->size > 0); if (section->size > 0) new_flags |= SEC_LOAD; @@ -1261,14 +1289,13 @@ _bfd_vms_slurp_egsd (bfd *abfd) new_flags |= SEC_CODE; new_flags &= ~SEC_DATA; } - if (!bfd_set_section_flags (abfd, section, new_flags)) + if (!bfd_set_section_flags (section, new_flags)) return FALSE; /* Give a non-overlapping vma to non absolute sections. */ - align_addr = (1 << section->alignment_power); - if ((base_addr % align_addr) != 0) - base_addr += (align_addr - (base_addr % align_addr)); - section->vma = (bfd_vma)base_addr; + align_addr = (bfd_vma) 1 << section->alignment_power; + base_addr = (base_addr + align_addr - 1) & -align_addr; + section->vma = base_addr; base_addr += section->size; } @@ -1292,18 +1319,22 @@ _bfd_vms_slurp_egsd (bfd *abfd) case EGSD__C_SYM: { - int nameoff; + unsigned int nameoff; struct vms_symbol_entry *entry; struct vms_egsy *egsy = (struct vms_egsy *) vms_rec; flagword old_flags; + if (offsetof (struct vms_egsy, flags) + 2 > gsd_size) + goto too_small; old_flags = bfd_getl16 (egsy->flags); if (old_flags & EGSY__V_DEF) nameoff = ESDF__B_NAMLNG; else nameoff = ESRF__B_NAMLNG; - entry = add_symbol (abfd, vms_rec + nameoff); + if (nameoff >= gsd_size) + goto too_small; + entry = add_symbol (abfd, vms_rec + nameoff, gsd_size - nameoff); if (entry == NULL) return FALSE; @@ -1320,8 +1351,7 @@ _bfd_vms_slurp_egsd (bfd *abfd) if (old_flags & EGSY__V_DEF) { - struct vms_esdf *esdf = (struct vms_esdf *)vms_rec; - long psindx; + struct vms_esdf *esdf = (struct vms_esdf *) vms_rec; entry->value = bfd_getl64 (esdf->value); if (PRIV (sections) == NULL) @@ -1331,7 +1361,9 @@ _bfd_vms_slurp_egsd (bfd *abfd) /* PR 21813: Check for an out of range index. */ if (psindx < 0 || psindx >= (int) PRIV (section_count)) { - _bfd_error_handler (_("corrupt EGSD record: its psindx field is too big (%#lx)"), + bad_psindx: + _bfd_error_handler (_("corrupt EGSD record: its psindx " + "field is too big (%#lx)"), psindx); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -1344,14 +1376,9 @@ _bfd_vms_slurp_egsd (bfd *abfd) entry->code_value = bfd_getl64 (esdf->code_address); psindx = bfd_getl32 (esdf->ca_psindx); - /* PR 21813: Check for an out of range index. */ + /* PR 21813: Check for an out of range index. */ if (psindx < 0 || psindx >= (int) PRIV (section_count)) - { - _bfd_error_handler (_("corrupt EGSD record: its psindx field is too big (%#lx)"), - psindx); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + goto bad_psindx; entry->code_section = PRIV (sections)[psindx]; } } @@ -1363,11 +1390,13 @@ _bfd_vms_slurp_egsd (bfd *abfd) struct vms_symbol_entry *entry; struct vms_egst *egst = (struct vms_egst *)vms_rec; flagword old_flags; + unsigned int nameoff = offsetof (struct vms_egst, namlng); old_flags = bfd_getl16 (egst->header.flags); - entry = add_symbol (abfd, &egst->namlng); - + if (nameoff >= gsd_size) + goto too_small; + entry = add_symbol (abfd, &egst->namlng, gsd_size - nameoff); if (entry == NULL) return FALSE; @@ -1379,19 +1408,12 @@ _bfd_vms_slurp_egsd (bfd *abfd) if (old_flags & EGSY__V_REL) { - long psindx; - if (PRIV (sections) == NULL) return FALSE; psindx = bfd_getl32 (egst->psindx); /* PR 21813: Check for an out of range index. */ if (psindx < 0 || psindx >= (int) PRIV (section_count)) - { - _bfd_error_handler (_("corrupt EGSD record: its psindx field is too big (%#lx)"), - psindx); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + goto bad_psindx; entry->section = PRIV (sections)[psindx]; } else @@ -1437,7 +1459,7 @@ _bfd_vms_slurp_egsd (bfd *abfd) /* Push value and section index. */ -static void +static bfd_boolean _bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc) { vms_debug2 ((4, "\n", @@ -1450,26 +1472,28 @@ _bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc) { bfd_set_error (bfd_error_bad_value); _bfd_error_handler (_("stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr)); - exit (1); + return FALSE; } + return TRUE; } /* Pop value and section index. */ -static void +static bfd_boolean _bfd_vms_pop (bfd *abfd, bfd_vma *val, unsigned int *rel) { if (PRIV (stackptr) == 0) { bfd_set_error (bfd_error_bad_value); _bfd_error_handler (_("stack underflow in _bfd_vms_pop")); - exit (1); + return FALSE; } PRIV (stackptr)--; *val = PRIV (stack[PRIV (stackptr)]).value; *rel = PRIV (stack[PRIV (stackptr)]).reloc; vms_debug2 ((4, "\n", (unsigned long)*val, *rel)); + return TRUE; } /* Routines to fill sections contents during tir/etir read. */ @@ -1854,19 +1878,23 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) while (ptr < maxptr) { - int cmd = bfd_getl16 (ptr); - int cmd_length = bfd_getl16 (ptr + 2); + int cmd, cmd_length; - ptr += 4; + if (ptr + 4 > maxptr) + goto corrupt_etir; + + cmd = bfd_getl16 (ptr); + cmd_length = bfd_getl16 (ptr + 2); /* PR 21589 and 21579: Check for a corrupt ETIR record. */ - if (cmd_length < 4 || (ptr + cmd_length > maxptr + 4)) + if (cmd_length < 4 || ptr + cmd_length > maxptr) { corrupt_etir: _bfd_error_handler (_("corrupt ETIR record encountered")); bfd_set_error (bfd_error_bad_value); return FALSE; } + ptr += 4; #if VMS_DEBUG _bfd_vms_debug (4, "etir: %s(%d)\n", @@ -1882,7 +1910,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 32 bit value of symbol (high bits set to 0). */ case ETIR__C_STA_GBL: _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); - _bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h)); + if (!_bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h))) + return FALSE; break; /* Stack longword @@ -1890,9 +1919,10 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 32 bit value, sign extend to 64 bit. */ case ETIR__C_STA_LW: - if (ptr + 4 >= maxptr) + if (ptr + 4 > maxptr) goto corrupt_etir; - _bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE); + if (!_bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE)) + return FALSE; break; /* Stack quadword @@ -1900,9 +1930,10 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 64 bit value of symbol. */ case ETIR__C_STA_QW: - if (ptr + 8 >= maxptr) + if (ptr + 8 > maxptr) goto corrupt_etir; - _bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE); + if (!_bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE)) + return FALSE; break; /* Stack psect base plus quadword offset @@ -1915,7 +1946,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { int psect; - if (ptr + 12 >= maxptr) + if (ptr + 12 > maxptr) goto corrupt_etir; psect = bfd_getl32 (ptr); if ((unsigned int) psect >= PRIV (section_count)) @@ -1926,7 +1957,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) return FALSE; } op1 = bfd_getl64 (ptr + 4); - _bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE); + if (!_bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE)) + return FALSE; } break; @@ -1941,7 +1973,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store byte: pop stack, write byte arg: -. */ case ETIR__C_STO_B: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; image_write_b (abfd, (unsigned int) op1 & 0xff); @@ -1950,7 +1983,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store word: pop stack, write word arg: -. */ case ETIR__C_STO_W: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; image_write_w (abfd, (unsigned int) op1 & 0xffff); @@ -1959,7 +1993,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store longword: pop stack, write longword arg: -. */ case ETIR__C_STO_LW: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 & RELC_SEC_BASE) { op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1); @@ -1982,7 +2017,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store quadword: pop stack, write quadword arg: -. */ case ETIR__C_STO_QW: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 & RELC_SEC_BASE) { op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1); @@ -2006,10 +2042,11 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { int size; - if (ptr + 4 >= maxptr) + if (ptr + 4 > maxptr) goto corrupt_etir; size = bfd_getl32 (ptr); - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; while (op1-- > 0) @@ -2072,7 +2109,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store offset to psect: pop stack, add low 32 bits to base of psect arg: none. */ case ETIR__C_STO_OFF: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (!(rel1 & RELC_SEC_BASE)) abort (); @@ -2089,7 +2127,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { unsigned int size; - if (ptr + 4 >= maxptr) + if (ptr + 4 > maxptr) goto corrupt_etir; size = bfd_getl32 (ptr); image_write (abfd, ptr + 4, size); @@ -2243,7 +2281,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Det relocation base: pop stack, set image location counter arg: none. */ case ETIR__C_CTL_SETRB: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (!(rel1 & RELC_SEC_BASE)) abort (); image_set_ptr (abfd, op1, rel1 & RELC_MASK, info); @@ -2252,7 +2291,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Augment relocation base: increment image location counter by offset arg: lw offset value. */ case ETIR__C_CTL_AUGRB: - if (ptr + 4 >= maxptr) + if (ptr + 4 > maxptr) goto corrupt_etir; op1 = bfd_getl32 (ptr); image_inc_ptr (abfd, op1); @@ -2261,7 +2300,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Define location: pop index, save location counter under index arg: none. */ case ETIR__C_CTL_DFLOC: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; dst_define_location (abfd, op1); @@ -2270,7 +2310,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Set location: pop index, restore location counter from index arg: none. */ case ETIR__C_CTL_STLOC: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; dst_restore_location (abfd, op1); @@ -2279,28 +2320,34 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Stack defined location: pop index, push location counter from index arg: none. */ case ETIR__C_CTL_STKDL: - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, dst_retrieve_location (abfd, op1), RELC_NONE); + if (!_bfd_vms_push (abfd, dst_retrieve_location (abfd, op1), + RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_NOP: /* No-op. */ break; case ETIR__C_OPR_ADD: /* Add. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 == RELC_NONE && rel2 != RELC_NONE) rel1 = rel2; else if (rel1 != RELC_NONE && rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op1 + op2, rel1); + if (!_bfd_vms_push (abfd, op1 + op2, rel1)) + return FALSE; break; case ETIR__C_OPR_SUB: /* Subtract. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 == RELC_NONE && rel2 != RELC_NONE) rel1 = rel2; else if ((rel1 & RELC_SEC_BASE) && (rel2 & RELC_SEC_BASE)) @@ -2311,69 +2358,90 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) } else if (rel1 != RELC_NONE && rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op2 - op1, rel1); + if (!_bfd_vms_push (abfd, op2 - op1, rel1)) + return FALSE; break; case ETIR__C_OPR_MUL: /* Multiply. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op1 * op2, RELC_NONE); + if (!_bfd_vms_push (abfd, op1 * op2, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_DIV: /* Divide. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) goto bad_context; if (op2 == 0) - _bfd_vms_push (abfd, 0, RELC_NONE); + { + if (!_bfd_vms_push (abfd, 0, RELC_NONE)) + return FALSE; + } else - _bfd_vms_push (abfd, op2 / op1, RELC_NONE); + { + if (!_bfd_vms_push (abfd, op2 / op1, RELC_NONE)) + return FALSE; + } break; case ETIR__C_OPR_AND: /* Logical AND. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op1 & op2, RELC_NONE); + if (!_bfd_vms_push (abfd, op1 & op2, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_IOR: /* Logical inclusive OR. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op1 | op2, RELC_NONE); + if (!_bfd_vms_push (abfd, op1 | op2, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_EOR: /* Logical exclusive OR. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, op1 ^ op2, RELC_NONE); + if (!_bfd_vms_push (abfd, op1 ^ op2, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_NEG: /* Negate. */ - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, -op1, RELC_NONE); + if (!_bfd_vms_push (abfd, -op1, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_COM: /* Complement. */ - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (rel1 != RELC_NONE) goto bad_context; - _bfd_vms_push (abfd, ~op1, RELC_NONE); + if (!_bfd_vms_push (abfd, ~op1, RELC_NONE)) + return FALSE; break; case ETIR__C_OPR_ASH: /* Arithmetic shift. */ - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; if (rel1 != RELC_NONE || rel2 != RELC_NONE) { bad_context: @@ -2385,7 +2453,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) op1 >>= -(int)op2; else /* Shift left. */ op1 <<= (int)op2; - _bfd_vms_push (abfd, op1, RELC_NONE); /* FIXME: sym. */ + if (!_bfd_vms_push (abfd, op1, RELC_NONE)) /* FIXME: sym. */ + return FALSE; break; case ETIR__C_OPR_INSV: /* Insert field. */ @@ -2399,14 +2468,20 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) break; case ETIR__C_OPR_SEL: /* Select. */ - _bfd_vms_pop (abfd, &op1, &rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; if (op1 & 0x01L) - _bfd_vms_pop (abfd, &op1, &rel1); + { + if (!_bfd_vms_pop (abfd, &op1, &rel1)) + return FALSE; + } else { - _bfd_vms_pop (abfd, &op1, &rel1); - _bfd_vms_pop (abfd, &op2, &rel2); - _bfd_vms_push (abfd, op1, rel1); + if (!_bfd_vms_pop (abfd, &op1, &rel1) + || !_bfd_vms_pop (abfd, &op2, &rel2)) + return FALSE; + if (!_bfd_vms_push (abfd, op1, rel1)) + return FALSE; } break; @@ -2441,7 +2516,7 @@ vms_slurp_debug (bfd *abfd) section = bfd_make_section (abfd, "$DST$"); if (!section) return FALSE; - if (!bfd_set_section_flags (abfd, section, flags)) + if (!bfd_set_section_flags (section, flags)) return FALSE; PRIV (dst_section) = section; } @@ -2601,6 +2676,22 @@ vms_initialize (bfd * abfd) return FALSE; } +/* Free malloc'd memory. */ + +static void +alpha_vms_free_private (bfd *abfd) +{ + struct module *module; + + free (PRIV (recrd.buf)); + free (PRIV (sections)); + free (PRIV (syms)); + free (PRIV (dst_ptr_offsets)); + + for (module = PRIV (modules); module; module = module->next) + free (module->file_table); +} + /* Check the format for a file being read. Return a (bfd_target *) if it's an object file or zero if not. */ @@ -2615,7 +2706,10 @@ alpha_vms_object_p (bfd *abfd) /* Allocate alpha-vms specific data. */ if (!vms_initialize (abfd)) - goto error_ret; + { + abfd->tdata.any = tdata_save; + return NULL; + } if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) goto err_wrong_format; @@ -2755,8 +2849,7 @@ alpha_vms_object_p (bfd *abfd) bfd_set_error (bfd_error_wrong_format); error_ret: - if (PRIV (recrd.buf)) - free (PRIV (recrd.buf)); + alpha_vms_free_private (abfd); if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = tdata_save; @@ -4204,7 +4297,7 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr, { case DST__K_MODBEG: module->name - = _bfd_vms_save_counted_string (ptr + DST_S_B_MODBEG_NAME, + = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME, maxptr - (ptr + DST_S_B_MODBEG_NAME)); curr_pc = 0; @@ -4222,7 +4315,7 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr, funcinfo = (struct funcinfo *) bfd_zalloc (abfd, sizeof (struct funcinfo)); funcinfo->name - = _bfd_vms_save_counted_string (ptr + DST_S_B_RTNBEG_NAME, + = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME, maxptr - (ptr + DST_S_B_RTNBEG_NAME)); funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS); funcinfo->next = module->func_table; @@ -4273,11 +4366,10 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr, { unsigned int fileid = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID); - char *filename - = _bfd_vms_save_counted_string (src_ptr + DST_S_B_SRC_DF_FILENAME, - (ptr + rec_length) - - (src_ptr + DST_S_B_SRC_DF_FILENAME) - ); + char *filename = _bfd_vms_save_counted_string + (abfd, + src_ptr + DST_S_B_SRC_DF_FILENAME, + ptr + rec_length - (src_ptr + DST_S_B_SRC_DF_FILENAME)); while (fileid >= module->file_table_count) { @@ -4623,7 +4715,7 @@ build_module_list (bfd *abfd) section and build the list of modules. This is sufficient since we can compute the start address and the end address of every module from the section contents. */ - bfd_size_type size = bfd_get_section_size (dmt); + bfd_size_type size = bfd_section_size (dmt); unsigned char *ptr, *end; ptr = (unsigned char *) bfd_alloc (abfd, size); @@ -6615,7 +6707,7 @@ evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel, fprintf (file, _(" bitmap: 0x%08x (count: %u):\n"), val, count); for (k = 0; k < 32; k++) - if (val & (1 << k)) + if (val & (1u << k)) { if (n == 0) fputs (" ", file); @@ -8336,6 +8428,27 @@ alpha_vms_link_hash_newfunc (struct bfd_hash_entry *entry, return (struct bfd_hash_entry *) ret; } +static void +alpha_vms_bfd_link_hash_table_free (bfd *abfd) +{ + struct alpha_vms_link_hash_table *t; + unsigned i; + + t = (struct alpha_vms_link_hash_table *) abfd->link.hash; + for (i = 0; i < VEC_COUNT (t->shrlibs); i++) + { + struct alpha_vms_shlib_el *shlib; + + shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i); + free (&VEC_EL (shlib->ca, bfd_vma, 0)); + free (&VEC_EL (shlib->lp, bfd_vma, 0)); + free (&VEC_EL (shlib->qr, struct alpha_vms_vma_ref, 0)); + } + free (&VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, 0)); + + _bfd_generic_link_hash_table_free (abfd); +} + /* Create an Alpha/VMS link hash table. */ static struct bfd_link_hash_table * @@ -8357,6 +8470,7 @@ alpha_vms_bfd_link_hash_table_create (bfd *abfd) VEC_INIT (ret->shrlibs); ret->fixup = NULL; + ret->root.hash_table_free = alpha_vms_bfd_link_hash_table_free; return &ret->root; } @@ -8912,8 +9026,8 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) return FALSE; } - bfd_get_outsymbols (abfd) = NULL; - bfd_get_symcount (abfd) = 0; + abfd->outsymbols = NULL; + abfd->symcount = 0; /* Mark all sections which will be included in the output file. */ for (o = abfd->sections; o != NULL; o = o->next) @@ -9283,35 +9397,24 @@ vms_close_and_cleanup (bfd * abfd) if (abfd == NULL || abfd->tdata.any == NULL) return TRUE; - if (abfd->format == bfd_archive) + if (abfd->format == bfd_object) { - bfd_release (abfd, abfd->tdata.any); - abfd->tdata.any = NULL; - return TRUE; - } - - if (PRIV (recrd.buf) != NULL) - free (PRIV (recrd.buf)); - - if (PRIV (sections) != NULL) - free (PRIV (sections)); - - bfd_release (abfd, abfd->tdata.any); - abfd->tdata.any = NULL; + alpha_vms_free_private (abfd); #ifdef VMS - if (abfd->direction == write_direction) - { - /* Last step on VMS is to convert the file to variable record length - format. */ - if (!bfd_cache_close (abfd)) - return FALSE; - if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename)) - return FALSE; - } + if (abfd->direction == write_direction) + { + /* Last step on VMS is to convert the file to variable record length + format. */ + if (!bfd_cache_close (abfd)) + return FALSE; + if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename)) + return FALSE; + } #endif + } - return TRUE; + return _bfd_generic_close_and_cleanup (abfd); } /* Called when a new section is created. */ @@ -9324,7 +9427,7 @@ vms_new_section_hook (bfd * abfd, asection *section) vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n", abfd, section->index, section->name)); - if (! bfd_set_section_alignment (abfd, section, 0)) + if (!bfd_set_section_alignment (section, 0)) return FALSE; vms_debug2 ((7, "%u: %s\n", section->index, section->name)); @@ -9412,11 +9515,11 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, else if (bfd_is_ind_section (sec)) ret->type = 'I'; else if ((symbol->flags & BSF_FUNCTION) - || (bfd_get_section_flags (abfd, sec) & SEC_CODE)) + || (bfd_section_flags (sec) & SEC_CODE)) ret->type = 'T'; - else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) + else if (bfd_section_flags (sec) & SEC_DATA) ret->type = 'D'; - else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) + else if (bfd_section_flags (sec) & SEC_ALLOC) ret->type = 'B'; else ret->type = '?';