📄 som.c
字号:
&& ! bfd_is_com_section (sym->section)) som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA; } break; case R_HPPA_GOTOFF: /* More PLABEL special cases. */ if (field == e_psel || field == e_lpsel || field == e_rpsel) *final_type = R_DATA_PLABEL; break; case R_HPPA_COMPLEX: /* The difference of two symbols needs *very* special handling. */ if (sym_diff) { final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[1] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[2] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[3] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0] || !final_types[1] || !final_types[2]) return NULL; if (field == e_fsel) *final_types[0] = R_FSEL; else if (field == e_rsel) *final_types[0] = R_RSEL; else if (field == e_lsel) *final_types[0] = R_LSEL; *final_types[1] = R_COMP2; *final_types[2] = R_COMP2; *final_types[3] = R_COMP1; final_types[4] = final_type; if (format == 32) *final_types[4] = R_DATA_EXPR; else *final_types[4] = R_CODE_EXPR; final_types[5] = NULL; break; } else break; case R_HPPA_NONE: case R_HPPA_ABS_CALL: /* Right now we can default all these. */ break; case R_HPPA_PCREL_CALL: {#ifndef NO_PCREL_MODES /* If we have short and long pcrel modes, then generate the proper mode selector, then the pcrel relocation. Redundant selectors will be eliminted as the relocs are sized and emitted. */ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; if (format == 17) *final_types[0] = R_SHORT_PCREL_MODE; else *final_types[0] = R_LONG_PCREL_MODE; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type;#endif break; } } return final_types;}/* Return the address of the correct entry in the PA SOM relocation howto table. */static reloc_howto_type *som_bfd_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code;{ if ((int) code < (int) R_NO_RELOCATION + 255) { BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code); return &som_hppa_howto_table[(int) code]; } return (reloc_howto_type *) 0;}/* Perform some initialization for an object. Save results of this initialization in the BFD. */static const bfd_target *som_object_setup (abfd, file_hdrp, aux_hdrp, current_offset) bfd *abfd; struct header *file_hdrp; struct som_exec_auxhdr *aux_hdrp; unsigned long current_offset;{ asection *section; int found; /* som_mkobject will set bfd_error if som_mkobject fails. */ if (som_mkobject (abfd) != true) return 0; /* Set BFD flags based on what information is available in the SOM. */ abfd->flags = BFD_NO_FLAGS; if (file_hdrp->symbol_total) abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; switch (file_hdrp->a_magic) { case DEMAND_MAGIC: abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P); break; case SHARE_MAGIC: abfd->flags |= (WP_TEXT | EXEC_P); break; case EXEC_MAGIC: abfd->flags |= (EXEC_P); break; case RELOC_MAGIC: abfd->flags |= HAS_RELOC; break;#ifdef SHL_MAGIC case SHL_MAGIC:#endif#ifdef DL_MAGIC case DL_MAGIC:#endif abfd->flags |= DYNAMIC; break; default: break; } /* Allocate space to hold the saved exec header information. */ obj_som_exec_data (abfd) = (struct som_exec_data *) bfd_zalloc (abfd, sizeof (struct som_exec_data)); if (obj_som_exec_data (abfd) == NULL) return NULL; /* The braindamaged OSF1 linker switched exec_flags and exec_entry! We used to identify OSF1 binaries based on NEW_VERSION_ID, but apparently the latest HPUX linker is using NEW_VERSION_ID now. It's about time, OSF has used the new id since at least 1992; HPUX didn't start till nearly 1995!. The new approach examines the entry field. If it's zero or not 4 byte aligned then it's not a proper code address and we guess it's really the executable flags. */ found = 0; for (section = abfd->sections; section; section = section->next) { if ((section->flags & SEC_CODE) == 0) continue; if (aux_hdrp->exec_entry >= section->vma && aux_hdrp->exec_entry < section->vma + section->_cooked_size) found = 1; } if (aux_hdrp->exec_entry == 0 || (aux_hdrp->exec_entry & 0x3) != 0 || ! found) { bfd_get_start_address (abfd) = aux_hdrp->exec_flags; obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry; } else { bfd_get_start_address (abfd) = aux_hdrp->exec_entry + current_offset; obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags; } bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10); bfd_get_symcount (abfd) = file_hdrp->symbol_total; /* Initialize the saved symbol table and string table to NULL. Save important offsets and sizes from the SOM header into the BFD. */ obj_som_stringtab (abfd) = (char *) NULL; obj_som_symtab (abfd) = (som_symbol_type *) NULL; obj_som_sorted_syms (abfd) = NULL; obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size; obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset; obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location + current_offset); obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location + current_offset); obj_som_exec_data (abfd)->system_id = file_hdrp->system_id; return abfd->xvec;}/* Convert all of the space and subspace info into BFD sections. Each space contains a number of subspaces, which in turn describe the mapping between regions of the exec file, and the address space that the program runs in. BFD sections which correspond to spaces will overlap the sections for the associated subspaces. */static booleansetup_sections (abfd, file_hdr, current_offset) bfd *abfd; struct header *file_hdr; unsigned long current_offset;{ char *space_strings; unsigned int space_index, i; unsigned int total_subspaces = 0; asection **subspace_sections, *section; /* First, read in space names. */ space_strings = bfd_malloc (file_hdr->space_strings_size); if (!space_strings && file_hdr->space_strings_size != 0) goto error_return; if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location, SEEK_SET) < 0) goto error_return; if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd) != file_hdr->space_strings_size) goto error_return; /* Loop over all of the space dictionaries, building up sections. */ for (space_index = 0; space_index < file_hdr->space_total; space_index++) { struct space_dictionary_record space; struct subspace_dictionary_record subspace, save_subspace; int subspace_index; asection *space_asect; char *newname; /* Read the space dictionary element. */ if (bfd_seek (abfd, (current_offset + file_hdr->space_location + space_index * sizeof space), SEEK_SET) < 0) goto error_return; if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space) goto error_return; /* Setup the space name string. */ space.name.n_name = space.name.n_strx + space_strings; /* Make a section out of it. */ newname = bfd_alloc (abfd, strlen (space.name.n_name) + 1); if (!newname) goto error_return; strcpy (newname, space.name.n_name); space_asect = bfd_make_section_anyway (abfd, newname); if (!space_asect) goto error_return; if (space.is_loadable == 0) space_asect->flags |= SEC_DEBUGGING; /* Set up all the attributes for the space. */ if (bfd_som_set_section_attributes (space_asect, space.is_defined, space.is_private, space.sort_key, space.space_number) == false) goto error_return; /* If the space has no subspaces, then we're done. */ if (space.subspace_quantity == 0) continue; /* Now, read in the first subspace for this space. */ if (bfd_seek (abfd, (current_offset + file_hdr->subspace_location + space.subspace_index * sizeof subspace), SEEK_SET) < 0) goto error_return; if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace) goto error_return; /* Seek back to the start of the subspaces for loop below. */ if (bfd_seek (abfd, (current_offset + file_hdr->subspace_location + space.subspace_index * sizeof subspace), SEEK_SET) < 0) goto error_return; /* Setup the start address and file loc from the first subspace record. */ space_asect->vma = subspace.subspace_start; space_asect->filepos = subspace.file_loc_init_value + current_offset; space_asect->alignment_power = log2 (subspace.alignment); if (space_asect->alignment_power == -1) goto error_return; /* Initialize save_subspace so we can reliably determine if this loop placed any useful values into it. */ memset (&save_subspace, 0, sizeof (struct subspace_dictionary_record)); /* Loop over the rest of the subspaces, building up more sections. */ for (subspace_index = 0; subspace_index < space.subspace_quantity; subspace_index++) { asection *subspace_asect; /* Read in the next subspace. */ if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace) goto error_return; /* Setup the subspace name string. */ subspace.name.n_name = subspace.name.n_strx + space_strings; newname = bfd_alloc (abfd, strlen (subspace.name.n_name) + 1); if (!newname) goto error_return; strcpy (newname, subspace.name.n_name); /* Make a section out of this subspace. */ subspace_asect = bfd_make_section_anyway (abfd, newname); if (!subspace_asect) goto error_return; /* Store private information about the section. */ if (bfd_som_set_subsection_attributes (subspace_asect, space_asect, subspace.access_control_bits, subspace.sort_key, subspace.quadrant) == false) goto error_return; /* Keep an easy mapping between subspaces and sections. Note we do not necessarily read the subspaces in the same order in which they appear in the object file. So to make the target index come out correctly, we store the location of the subspace header in target index, then sort using the location of the subspace header as the key. Then we can assign correct subspace indices. */ total_subspaces++; subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace); /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified by the access_control_bits in the subspace header. */ switch (subspace.access_control_bits >> 4) { /* Readonly data. */ case 0x0: subspace_asect->flags |= SEC_DATA | SEC_READONLY; break; /* Normal data. */ case 0x1: subspace_asect->flags |= SEC_DATA; break; /* Readonly code and the gateways. Gateways have other attributes which do not map into anything BFD knows about. */ case 0x2: case 0x4: case 0x5: case 0x6: case 0x7: subspace_asect->flags |= SEC_CODE | SEC_READONLY; break; /* dynamic (writable) code. */ case 0x3: subspace_asect->flags |= SEC_CODE; break; } if (subspace.dup_common || subspace.is_common) subspace_asect->flags |= SEC_IS_COMMON; else if (subspace.subspace_length > 0) subspace_asect->flags |= SEC_HAS_CONTENTS; if (subspace.is_loadable) subspace_asect->flags |= SEC_ALLOC | SEC_LOAD; else subspace_asect->flags |= SEC_DEBUGGING; if (subspace.code_only) subspace_asect->flags |= SEC_CODE; /* Both file_loc_init_value and initialization_length will be zero for a BSS like subspace. */ if (subspace.file_loc_init_value == 0 && subspace.initialization_length == 0) subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD | SEC_HAS_CONTENTS); /* This subspace has relocations. The fixup_request_quantity is a byte count for the number of entries in the relocation stream; it is not the actual number of relocations in the subspace. */ if (subspace.fixup_request_quantity != 0) { subspace_asect->flags |= SEC_RELOC; subspace_asect->rel_filepos = subspace.fixup_request_index; som_section_data (subspace_asect)->reloc_size = subspace.fixup_request_quantity; /* We can not determine this yet. When we read in the relocation table the correct value will be filled in. */ subspace_asect->reloc_count = -1; } /* Update save_subspace if appropriate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -