GP-5942: Loader for "System Object Model" binaries

This commit is contained in:
Ryan Kurtz
2025-10-09 08:06:13 -04:00
parent f255b37871
commit bb63706226
26 changed files with 4148 additions and 2 deletions

View File

@@ -40,8 +40,16 @@ public class Omf51ModuleHeader extends OmfRecord {
@Override
public void parseData() throws IOException, OmfException {
moduleName = OmfUtils.readString(dataReader);
dataReader.readNextByte();
trnId = dataReader.readNextByte();
switch (trnId) {
case (byte) 0xfd: // ASM51
case (byte) 0xfe: // PL/M-51
case (byte) 0xff: // RL51
break;
default:
throw new OmfException("Invalid TRN ID: 0x%x".formatted(trnId));
}
}
/**

View File

@@ -0,0 +1,59 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Abstract parent class for SOM auxiliary headers
*/
public abstract class SomAuxHeader implements StructConverter {
protected SomAuxId auxId;
/**
* Creates a new {@link SomAuxHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary header
* @throws IOException if there was an IO-related error
*/
public SomAuxHeader(BinaryReader reader) throws IOException {
auxId = new SomAuxId(reader);
}
/**
* {@return this {@link SomAuxHeader}'s {@link SomAuxId aux ID}}
*/
public SomAuxId getAuxId() {
return auxId;
}
/**
* {@return the length in bytes of this {@link SomAuxHeader auxiliary header} (including the
* size of the aux id)}
*/
public long getLength() {
return auxId.getLength() + SomAuxId.SIZE;
}
@Override
public abstract DataType toDataType() throws DuplicateNameException, IOException;
}

View File

@@ -0,0 +1,43 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
/**
* A class for reading/creating SOM auxiliary headers
*/
public class SomAuxHeaderFactory {
public static SomAuxHeader readNextAuxHeader(BinaryReader reader) throws IOException {
long origReaderIndex = reader.getPointerIndex();
SomAuxId auxId = new SomAuxId(reader);
reader.setPointerIndex(origReaderIndex);
return switch (auxId.getType()) {
case SomConstants.EXEC_AUXILIARY_HEADER:
yield new SomExecAuxHeader(reader);
case SomConstants.LINKER_FOOTPRINT:
yield new SomLinkerFootprintAuxHeader(reader);
case SomConstants.PRODUCT_SPECIFICS:
yield new SomProductSpecificsAuxHeader(reader);
default:
yield new SomUnknownAuxHeader(reader);
};
}
}

View File

@@ -0,0 +1,138 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code aux_id} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomAuxId implements StructConverter {
/** The size in bytes of a {@link SomAuxId} */
public static final int SIZE = 0x8;
private boolean mandatory;
private boolean copy;
private boolean append;
private boolean ignore;
private int reserved;
private int type;
private long length;
/**
* Creates a new {@link SomAuxId}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary ID
* @throws IOException if there was an IO-related error
*/
public SomAuxId(BinaryReader reader) throws IOException {
int bitfield = reader.readNextInt();
type = bitfield & 0xffff;
reserved = (bitfield >> 16) & 0xfff;
ignore = ((bitfield >> 28) & 0x1) != 0;
append = ((bitfield >> 29) & 0x1) != 0;
copy = ((bitfield >> 30) & 0x1) != 0;
mandatory = ((bitfield >> 31) & 0x1) != 0;
length = reader.readNextUnsignedInt();
}
/**
* {@return whether or not this auxiliary header contains information that the linker must
* understand}
*/
public boolean getMandatory() {
return mandatory;
}
/**
* {@return whether or not this auxiliary header is to be copied without modification to any new
* SOM created from this SOM}
*/
public boolean getCopy() {
return copy;
}
/**
* {@return whether or not this auxiliary header is to be copied without modification to any new
* SOM created from this SOM, except that multiple entries with the same type and append set of
* “action flags” (i.e., mandatory, copy, append, ignore) should be merged (concatenation of the
* data portion)}
*/
public boolean getAppend() {
return append;
}
/**
* {@return whether or not this auxiliary header should be ignored if its type field is unknown
* (i.e., do not copy, do not merge)}
*/
public boolean getIgnore() {
return ignore;
}
/**
* {@return the reserved value}
*/
public int getReserved() {
return reserved;
}
/**
* {@return the type of auxiliary header}
*
* @see SomConstants
*/
public int getType() {
return type;
}
/**
* {@return the length of the auxiliary header in bytes (this value does NOT include the two
* word identifiers at the front of the header)}
*/
public long getLength() {
return length;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("aux_id", SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(DWORD, 1, "mandatory", null);
struct.addBitField(DWORD, 1, "copy", null);
struct.addBitField(DWORD, 1, "append", null);
struct.addBitField(DWORD, 1, "ignore", null);
struct.addBitField(DWORD, 12, "reserved", null);
struct.addBitField(DWORD, 16, "type", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "length", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,141 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code compilation_unit} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomCompilationUnit implements StructConverter {
/** The size in bytes of a {@link SomCompilationUnit} */
public static final int SIZE = 0x24;
private String name;
private String languageName;
private String productId;
private String versionId;
private int reserved;
private boolean chunkFlag;
private SomSysClock compileTime;
private SomSysClock sourceTime;
/**
* Creates a new {@link SomCompilationUnit}
*
* @param reader A {@link BinaryReader} positioned at the start of the record
* @param symbolStringsLocation The starting index of the symbol strings
* @throws IOException if there was an IO-related error
*/
public SomCompilationUnit(BinaryReader reader, long symbolStringsLocation) throws IOException {
name = reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
languageName = reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
productId = reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
versionId = reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
int bitfield = reader.readNextInt();
chunkFlag = (bitfield & 0x1) != 0;
reserved = (bitfield >> 1) & 0x7fffffff;
compileTime = new SomSysClock(reader);
sourceTime = new SomSysClock(reader);
}
/**
* {@return the compilation unit name}
*/
public String getName() {
return name;
}
/**
* {@return the language name}
*/
public String getLanguageName() {
return languageName;
}
/**
* {@return the product ID}
*/
public String getProductId() {
return productId;
}
/**
* {@return the version ID}
*/
public String getVersionId() {
return versionId;
}
/**
* {@return the reserved value}
*/
public int getReserved() {
return reserved;
}
/**
* {@return whether or not the compilation unit is not the first SOM in a multiple chunk
* compilation}
*/
public boolean getChunkFlag() {
return chunkFlag;
}
/**
* {@return the compile time}
*/
public SomSysClock getCompileTime() {
return compileTime;
}
/**
* {@return the source time}
*/
public SomSysClock getSourceTime() {
return sourceTime;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("compilation_unit", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "name", null);
struct.add(DWORD, "language_name", null);
struct.add(DWORD, "product_id", null);
struct.add(DWORD, "version_id", null);
try {
struct.addBitField(DWORD, 31, "reserved", null);
struct.addBitField(DWORD, 1, "chunk_flag", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(compileTime.toDataType(), "compile_time", null);
struct.add(sourceTime.toDataType(), "source_time", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,93 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
/**
* SOM constant values
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomConstants {
// System IDs
public static final int SYSTEM_PA_RISC_1_0 = 0x20b;
public static final int SYSTEM_PA_RISC_1_1 = 0x210;
public static final int SYSTEM_PA_RISC_2_0 = 0x214;
// Magic numbers
public static final int MAGIC_LIBRARY = 0x104;
public static final int MAGIC_RELOCATABLE = 0x106;
public static final int MAGIC_NON_SHAREABLE_EXE = 0x107;
public static final int MAGIC_SHAREABLE_EXE = 0x108;
public static final int MAGIC_SHARABLE_DEMAND_LOADABLE_EXE = 0x10b;
public static final int MAGIC_DYNAMIC_LOAD_LIBRARY = 0x10d;
public static final int MAGIC_SHARED_LIBRARY = 0x10e;
public static final int MAGIC_RELOCATABLE_LIBRARY = 0x0619;
// Version IDs
public static final int VERSION_OLD = 0x85082112;
public static final int VERSION_NEW = 0x87102412;
// Auxiliary header types
public static final int TYPE_NULL = 0;
public static final int LINKER_FOOTPRINT = 1;
public static final int MEP_IX_PROGRAM = 2;
public static final int DEBUGGER_FOOTPRINT = 3;
public static final int EXEC_AUXILIARY_HEADER = 4;
public static final int IPL_AUXILIARY_HEADER = 5;
public static final int VERSION_STRIING = 6;
public static final int MPE_IX_PROGRAM = 7;
public static final int MPE_IX_SOM = 8;
public static final int COPYRIGHT = 9;
public static final int SHARED_LIBARY_VERSION_INFORMATION = 10;
public static final int PRODUCT_SPECIFICS = 11;
public static final int NETWARE_LOADABLE_MODULE = 12;
// Symbol types
public static final int SYMBOL_NULL = 0;
public static final int SYMBOL_ABSOLUTE = 1;
public static final int SYMBOL_DATA = 2;
public static final int SYMBOL_CODE = 3;
public static final int SYMBOL_PRI_PROG = 4;
public static final int SYMBOL_SEC_PROG = 5;
public static final int SYMBOL_ENTRY = 6;
public static final int SYMBOL_STORAGE = 7;
public static final int SYMBOL_STUB = 8;
public static final int SYMBOL_MODULE = 9;
public static final int SYMBOL_SYM_EXT = 10;
public static final int SYMBOL_ARG_EXT = 11;
public static final int SYMBOL_MILLICODE = 12;
public static final int SYMBOL_PLABEL = 13;
public static final int SYMBOL_OCT_DIS = 14;
public static final int SYMBOL_MILLI_EXT = 15;
public static final int SYMBOL_TSTORAGE = 16;
public static final int SYMBOL_COMDAT = 17;
// Symbol scopes
public static final int SYMBOL_SCOPE_UNSAT = 0;
public static final int SYMBOL_SCOPE_EXTERNAL = 1;
public static final int SYMBOL_SCOPE_LOCAL = 2;
public static final int SYMBOL_SCOPE_UNIVERSAL = 3;
// Dynamic relocation types
public static final int DR_PLABEL_EXT = 1;
public static final int DR_PLABEL_INT = 2;
public static final int DR_DATA_EXT = 3;
public static final int DR_DATA_INT = 4;
public static final int DR_PROPAGATE = 5;
public static final int DR_INVOKE = 6;
public static final int DR_TEXT_INT = 7;
}

View File

@@ -0,0 +1,58 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code DLT} value
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomDltEntry implements StructConverter {
/** The size in bytes of a {@link SomDltEntry} */
public static final int SIZE = 0x4;
private int value;
/**
* Creates a new {@link SomDltEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the DLT
* @throws IOException if there was an IO-related error
*/
public SomDltEntry(BinaryReader reader) throws IOException {
value = reader.readNextInt();
}
/**
* {@return the value of the DLT entry}
*/
public int getValue() {
return value;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return POINTER;
}
}

View File

@@ -0,0 +1,591 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import static ghidra.program.model.data.DataUtilities.ClearDataMode.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a SOM {@code dl_header} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomDynamicLoaderHeader implements StructConverter {
/** The size in bytes of a {@link SomDynamicLoaderHeader} */
public static final int SIZE = 0x70;
private int hdrVersion;
private int ltptrValue;
private int shlibListLoc;
private int shlibListCount;
private int importListLoc;
private int importListCount;
private int hashTableLoc;
private int hashTableSize;
private int exportListLoc;
private int exportListCount;
private int stringTableLoc;
private int stringTableSize;
private int drelocLoc;
private int drelocCount;
private int dltLoc;
private int pltLoc;
private int dltCount;
private int pltCount;
private short highwaterMark;
private short flags;
private int exportExtLoc;
private int moduleLoc;
private int moduleCount;
private int elaborator;
private int initializer;
private int embeddedPath;
private int initializerCount;
private int tdsize;
private int fastbindListLoc;
private Address textAddr;
private Address dataAddr;
private List<SomShlibListEntry> shlibs = new ArrayList<>();
private List<SomImportEntry> imports = new ArrayList<>();
private List<SomExportEntry> exports = new ArrayList<>();
private List<SomDynamicRelocation> drelocs = new ArrayList<>();
private List<SomPltEntry> plt = new ArrayList<>();
private List<SomDltEntry> dlt = new ArrayList<>();
private List<SomExportEntryExt> exportExtensions = new ArrayList<>();
private List<SomModuleEntry> modules = new ArrayList<>();
/**
* Creates a new {@link SomDynamicLoaderHeader}
*
* @param program The {@link Program}
* @param textAddr The {@link Address} of the "text" space
* @param dataAddr The {@link Address} of the "data" space
* @throws IOException if there was an IO-related error
*/
public SomDynamicLoaderHeader(Program program, Address textAddr, Address dataAddr)
throws IOException {
if (textAddr == null) {
throw new IOException("Address of text space required to create dynamic loader header");
}
if (dataAddr == null) {
throw new IOException("Address of data space required to create dynamic loader header");
}
BinaryReader textReader =
new BinaryReader(new MemoryByteProvider(program.getMemory(), textAddr), false);
BinaryReader dataReader =
new BinaryReader(new MemoryByteProvider(program.getMemory(), dataAddr), false);
hdrVersion = textReader.readNextInt();
ltptrValue = textReader.readNextInt();
shlibListLoc = textReader.readNextInt();
shlibListCount = textReader.readNextInt();
importListLoc = textReader.readNextInt();
importListCount = textReader.readNextInt();
hashTableLoc = textReader.readNextInt();
hashTableSize = textReader.readNextInt();
exportListLoc = textReader.readNextInt();
exportListCount = textReader.readNextInt();
stringTableLoc = textReader.readNextInt();
stringTableSize = textReader.readNextInt();
drelocLoc = textReader.readNextInt();
drelocCount = textReader.readNextInt();
dltLoc = textReader.readNextInt();
pltLoc = textReader.readNextInt();
dltCount = textReader.readNextInt();
pltCount = textReader.readNextInt();
highwaterMark = textReader.readNextShort();
flags = textReader.readNextShort();
exportExtLoc = textReader.readNextInt();
moduleLoc = textReader.readNextInt();
moduleCount = textReader.readNextInt();
elaborator = textReader.readNextInt();
initializer = textReader.readNextInt();
embeddedPath = textReader.readNextInt();
initializerCount = textReader.readNextInt();
tdsize = textReader.readNextInt();
fastbindListLoc = textReader.readNextInt();
this.textAddr = textAddr;
this.dataAddr = dataAddr;
if (shlibListLoc > 0) {
textReader.setPointerIndex(shlibListLoc);
for (int i = 0; i < shlibListCount; i++) {
shlibs.add(new SomShlibListEntry(textReader, stringTableLoc));
}
}
if (importListCount > 0) {
textReader.setPointerIndex(importListLoc);
for (int i = 0; i < importListCount; i++) {
imports.add(new SomImportEntry(textReader, stringTableLoc));
}
}
if (exportListCount > 0) {
textReader.setPointerIndex(exportListLoc);
for (int i = 0; i < exportListCount; i++) {
exports.add(new SomExportEntry(textReader, stringTableLoc));
}
}
if (drelocCount > 0) {
textReader.setPointerIndex(drelocLoc);
for (int i = 0; i < drelocCount; i++) {
drelocs.add(new SomDynamicRelocation(textReader));
}
}
if (pltCount > 0) {
dataReader.setPointerIndex(pltLoc);
for (int i = 0; i < pltCount; i++) {
plt.add(new SomPltEntry(dataReader));
}
}
if (dltCount > 0) {
dataReader.setPointerIndex(dltLoc);
for (int i = 0; i < dltCount; i++) {
dlt.add(new SomDltEntry(dataReader));
}
}
if (exportExtLoc > 0) {
textReader.setPointerIndex(exportExtLoc);
for (int i = 0; i < exportListCount; i++) {
exportExtensions.add(new SomExportEntryExt(textReader));
}
}
if (moduleCount > 0) {
textReader.setPointerIndex(moduleLoc);
for (int i = 0; i < moduleCount; i++) {
modules.add(new SomModuleEntry(textReader));
}
}
}
/**
* {@return the version of the DL header}
*/
public int getHdrVersion() {
return hdrVersion;
}
/**
* {@return the data-relative offset of the Linkage Table pointer}
*/
public int getLtptrValue() {
return ltptrValue;
}
/**
* {@return the text-relative offset of the shared library list}
*/
public int getShlibListLoc() {
return shlibListLoc;
}
/**
* {@return the number of entries in the shared library list}
*/
public int getShlibListCount() {
return shlibListCount;
}
/**
* {@return the text-relative offset of the import list}
*/
public int getImportListLoc() {
return importListLoc;
}
/**
* {@return the number of entries in the import list}
*/
public int getImportListCount() {
return importListCount;
}
/**
* {@return the text-relative offset of the hash table}
*/
public int getHashTableLoc() {
return hashTableLoc;
}
/**
* {@return the number of slots used in the hash table}
*/
public int getHashTableSize() {
return hashTableSize;
}
/**
* {@return the text-relative offset of the export list}
*/
public int getExportListLoc() {
return exportListLoc;
}
/**
* {@return the number of export entries}
*/
public int getExportListCount() {
return exportListCount;
}
/**
* {@return the text-relative offset of the string table}
*/
public int getStringTableLoc() {
return stringTableLoc;
}
/**
* {@return the length of the string table}
*/
public int getStringTableSize() {
return stringTableSize;
}
/**
* {@return the text-relative offset of the dynamic relocation records}
*/
public int getDrelocLoc() {
return drelocLoc;
}
/**
* {@return the number of dynamic relocation records generated}
*/
public int getDrelocCount() {
return drelocCount;
}
/**
* {@return the offset in the $DATA$ space of the Data Linkage Table}
*/
public int getDltLoc() {
return dltLoc;
}
/**
* {@return the offset in the $DATA$ space of the Procedure Linkage Table}
*/
public int getPltLoc() {
return pltLoc;
}
/**
* {@return the number of entries in the DLT}
*/
public int getDltCount() {
return dltCount;
}
/**
* {@return the number of entries in the PLT}
*/
public int getPltCount() {
return pltCount;
}
/**
* {@return the highest version number of any symbol defined in the shared library or in the
* set of highwater marks of the shared libraries in the shared library list}
*/
public short getHighwaterMark() {
return highwaterMark;
}
/**
* {@return the flags}
*/
public short getFlags() {
return flags;
}
/**
* {@return the text-relative offset of the export extension table}
*/
public int getExportExtLoc() {
return exportExtLoc;
}
/**
* {@return the text-relative offset of the module table}
*/
public int getModuleLoc() {
return moduleLoc;
}
/**
* {@return the number of modules in the module table}
*/
public int getModuleCount() {
return moduleCount;
}
/**
* {@return the index into the import table if the elab_ref bit in the flags field is set}
*/
public int getElaborator() {
return elaborator;
}
/**
* {@return the index into the import table if the init_ref bit in the flags field is set and
* the initializer_count field is set 0}
*/
public int getInitializer() {
return initializer;
}
/**
* {@return the index into the shared library string table}
*/
public int getEmbeddedPath() {
return embeddedPath;
}
/**
* {@return the number of initializers declared}
*/
public int getInitializerCount() {
return initializerCount;
}
/**
* {@return the size of the TSD area}
*/
public int getTdsize() {
return tdsize;
}
/**
* {@return the text-relative offset of fastbind info}
*/
public int getFastbindListLoc() {
return fastbindListLoc;
}
/**
* {@return the {@link Address} of the "text" space}
*/
public Address getTextAddress() {
return textAddr;
}
/**
* {@return the {@link Address} of the "data" space}
*/
public Address getDataAddress() {
return dataAddr;
}
/**
* {@return the {@link List} of {@link SomShlibListEntry shared library entries}}
*/
public List<SomShlibListEntry> getShlibs() {
return shlibs;
}
/**
* {@return the {@link List} of {@link SomImportEntry import entries}}
*/
public List<SomImportEntry> getImports() {
return imports;
}
/**
* {@return the {@link List} of {@link SomExportEntry export entries}}
*/
public List<SomExportEntry> getExports() {
return exports;
}
/**
* {@return the {@link List} of {@link SomDynamicRelocation dynamic relocation entries}}
*/
public List<SomDynamicRelocation> getDynamicRelocations() {
return drelocs;
}
/**
* {@return the {@link List} of {@link SomPltEntry PLT entries}}
*/
public List<SomPltEntry> getPlt() {
return plt;
}
/**
* {@return the {@link List} of {@link SomDltEntry DLT entries}}
*/
public List<SomDltEntry> getDlt() {
return dlt;
}
/**
* {@return the {@link List} of {@link SomExportEntryExt export entry extensions}
*/
public List<SomExportEntryExt> getExportExtensions() {
return exportExtensions;
}
/**
* {@return the {@link List} of {@link SomModuleEntry module entries}}
*/
public List<SomModuleEntry> getModules() {
return modules;
}
/**
* Marks up this header
*
* @param program The {@link Program}
* @param monitor A cancellable monitor
* @throws Exception if there was a problem during markup
*/
public void markup(Program program, TaskMonitor monitor) throws Exception {
Listing listing = program.getListing();
DataUtilities.createData(program, textAddr, toDataType(), -1, CHECK_FOR_SPACE);
monitor.initialize(shlibListCount, "Marking up shared library list...");
for (int i = 0; i < shlibListCount; i++) {
monitor.increment();
SomShlibListEntry shlib = shlibs.get(i);
Address addr = textAddr.add(shlibListLoc + i * SomShlibListEntry.SIZE);
DataUtilities.createData(program, addr, shlib.toDataType(), -1, CHECK_FOR_SPACE);
listing.setComment(addr, CommentType.EOL, shlib.getShlibName());
}
monitor.initialize(importListCount, "Marking up imports list...");
for (int i = 0; i < importListCount; i++) {
monitor.increment();
SomImportEntry entry = imports.get(i);
Address addr = textAddr.add(importListLoc + i * SomImportEntry.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
listing.setComment(addr, CommentType.EOL, entry.getName());
}
monitor.initialize(exportListCount, "Marking up exports list...");
for (int i = 0; i < exportListCount; i++) {
monitor.increment();
SomExportEntry entry = exports.get(i);
Address addr = textAddr.add(exportListLoc + i * SomExportEntry.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
listing.setComment(addr, CommentType.EOL, entry.getName());
}
monitor.initialize(drelocCount, "Marking up dreloc list...");
for (int i = 0; i < drelocCount; i++) {
monitor.increment();
SomDynamicRelocation entry = drelocs.get(i);
Address addr = textAddr.add(drelocLoc + i * SomDynamicRelocation.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
switch (entry.getType()) {
case SomConstants.DR_PLABEL_EXT:
case SomConstants.DR_DATA_EXT:
listing.setComment(addr, CommentType.EOL,
imports.get(entry.getSymbol()).getName());
}
}
monitor.initialize(dltCount, "Marking up DLT entries...");
for (int i = 0; i < dltCount; i++) {
monitor.increment();
SomDltEntry entry = dlt.get(i);
Address addr = dataAddr.add(dltLoc + i * SomDltEntry.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
}
monitor.initialize(pltCount, "Marking up PLT entries...");
for (int i = 0; i < pltCount; i++) {
monitor.increment();
SomPltEntry entry = plt.get(i);
Address addr = dataAddr.add(pltLoc + i * SomPltEntry.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
}
monitor.initialize(exportListCount, "Marking up export extensions list...");
for (int i = 0; i < exportListCount && exportExtLoc > 0; i++) {
monitor.increment();
SomExportEntryExt entry = exportExtensions.get(i);
Address addr = textAddr.add(exportExtLoc + i * SomExportEntryExt.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
listing.setComment(addr, CommentType.EOL, exports.get(i).getName());
}
monitor.initialize(moduleCount, "Marking up modules list...");
for (int i = 0; i < moduleCount; i++) {
monitor.increment();
SomModuleEntry entry = modules.get(i);
Address addr = textAddr.add(moduleLoc + i * SomModuleEntry.SIZE);
DataUtilities.createData(program, addr, entry.toDataType(), -1, CHECK_FOR_SPACE);
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("dl_header", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "hdr_version", "header version number");
struct.add(DWORD, "ltptr_value", "data offset of LT pointer (R19)");
struct.add(DWORD, "shlib_list_loc", "text offset of shlib list");
struct.add(DWORD, "shlib_list_count", "count of items in shlib list");
struct.add(DWORD, "import_list_loc", "text offset of import list");
struct.add(DWORD, "import_list_count", "count of items in import list");
struct.add(DWORD, "hash_table_loc", "text offset of export hash table");
struct.add(DWORD, "hash_table_size", "count of slots in export hash table");
struct.add(DWORD, "export_list_loc", "text offset of export list");
struct.add(DWORD, "export_list_count", "count of items in export list");
struct.add(DWORD, "string_table_loc", "text offset of string table");
struct.add(DWORD, "string_table_size", "length in bytes of string table");
struct.add(DWORD, "dreloc_loc", "text offset of dynamic reloc records");
struct.add(DWORD, "dreloc_count", "number of dynamic relocation records");
struct.add(DWORD, "dlt_loc", "data offset of data linkage table");
struct.add(DWORD, "plt_loc", "data offset of procedure linkage table");
struct.add(DWORD, "dlt_count", "number of dlt entries in linkage table");
struct.add(DWORD, "plt_count", "number of plt entries in linkage table");
struct.add(WORD, "highwater_mark", "highest version number seen in lib or in shlib list");
struct.add(WORD, "flags", "various flags");
struct.add(DWORD, "export_ext_loc", "text offset of export extension tbl");
struct.add(DWORD, "module_loc", "text offset of module table");
struct.add(DWORD, "module_count", "number of module entries");
struct.add(DWORD, "elaborator", "import index of elaborator");
struct.add(DWORD, "initializer", "import index of initializer");
struct.add(DWORD, "embedded_path", "index into string table for search path");
struct.add(DWORD, "initializer_count", "count of items in initializer import list");
struct.add(DWORD, "tdsize", "size of the TSD area");
struct.add(DWORD, "fastbind_list_loc", "text-relative offset of fastbind info");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,126 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code dreloc_record} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomDynamicRelocation implements StructConverter {
/** The size in bytes of a {@link SomDynamicRelocation} */
public static final int SIZE = 0x14;
private int shlib;
private int symbol;
private int location;
private int value;
private int type;
private byte reserved;
private short moduleIndex;
/**
* Creates a new {@link SomDynamicRelocation}
*
* @param reader A {@link BinaryReader} positioned at the start of the dynamic relocation list
* @throws IOException if there was an IO-related error
*/
public SomDynamicRelocation(BinaryReader reader) throws IOException {
shlib = reader.readNextInt();
symbol = reader.readNextInt();
location = reader.readNextInt();
value = reader.readNextInt();
type = reader.readNextUnsignedByte();
reserved = reader.readNextByte();
moduleIndex = reader.readNextShort();
}
/**
* {@return the shared library name (currently a reserved field)}
*/
public int getShlib() {
return shlib;
}
/**
* {@return the index into the import table if the relocation is an external type}
*/
public int getSymbol() {
return symbol;
}
/**
* {@return the data-relative offset of the data item the dreloc record refers to}
*/
public int getLocation() {
return location;
}
/**
* {@return the text or data-relative offset to use for a patch if it is an internal fixup type}
*/
public int getValue() {
return value;
}
/**
* {@return the type of dynamic relocation}
*
* @see SomConstants
*/
public int getType() {
return type;
}
/**
* {@return the reserved value}
*/
public byte getReserved() {
return reserved;
}
/**
* {@return the module index (currently reserved)}
*/
public short getModuleIndex() {
return moduleIndex;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("dreloc_record", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "shlib", "reserved");
struct.add(DWORD, "symbol",
"index into import table of shlib if *_EXT type. low order 16 bits used for module index if *_INT type");
struct.add(DWORD, "location", "offset of location to patch data-relative");
struct.add(DWORD, "value",
"text or data-relative offset to use for patch if internal-type fixup");
struct.add(BYTE, "type", "type of dreloc record");
struct.add(BYTE, "reserved", "currently unused");
struct.add(WORD, "module_index", "reserved");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,150 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code som_exec_auxhdr} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomExecAuxHeader extends SomAuxHeader {
private long execTextSize;
private long execTextMem;
private long execTextFile;
private long execDataSize;
private long execDataMem;
private long execDataFile;
private long execBssSize;
private long execEntry;
private long execFlags;
private long execBssFill;
/**
* Creates a new {@link SomExecAuxHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary header
* @throws IOException if there was an IO-related error
*/
public SomExecAuxHeader(BinaryReader reader) throws IOException {
super(reader);
execTextSize = reader.readNextUnsignedInt();
execTextMem = reader.readNextUnsignedInt();
execTextFile = reader.readNextUnsignedInt();
execDataSize = reader.readNextUnsignedInt();
execDataMem = reader.readNextUnsignedInt();
execDataFile = reader.readNextUnsignedInt();
execBssSize = reader.readNextUnsignedInt();
execEntry = reader.readNextUnsignedInt();
execFlags = reader.readNextUnsignedInt();
execBssFill = reader.readNextUnsignedInt();
}
/**
* {@return the text size in bytes}
*/
public long getExecTextSize() {
return execTextSize;
}
/**
* {@return the offset of text in memory}
*/
public long getExecTextMem() {
return execTextMem;
}
/**
* {@return the location of text in file}
*/
public long getExecTextFile() {
return execTextFile;
}
/**
* {@return the initialized data size in bytes}
*/
public long getExecDataSize() {
return execDataSize;
}
/**
* {@return the offset of data in memory}
*/
public long getExecDataMem() {
return execDataMem;
}
/**
* {@return the location of data in file}
*/
public long getExecDataFile() {
return execDataFile;
}
/**
* {@return the uninitialized data (BSS) size in bytes}
*/
public long getExecBssSize() {
return execBssSize;
}
/**
* {@return the offset of entrypoint}
*/
public long getExecEntry() {
return execEntry;
}
/**
* {@return the loader flags}
*/
public long getExecFlags() {
return execFlags;
}
/**
* {@return BSS initialization value}
*/
public long getExecBssFill() {
return execBssFill;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("som_exec_auxhdr", 0);
struct.setPackingEnabled(true);
struct.add(auxId.toDataType(), "som_auxhdr", null);
struct.add(DWORD, "exec_tsize", "text size in bytes");
struct.add(DWORD, "exec_tmem", "offset of text in memory");
struct.add(DWORD, "exec_tfile", "location of text in file");
struct.add(DWORD, "exec_dsize", "initialized data size in bytes");
struct.add(DWORD, "exec_dmem", "offset of data in memory");
struct.add(DWORD, "exec_dfile", "location of data in file");
struct.add(DWORD, "exec_bsize", "uninitialized data (bss) size in bytes");
struct.add(DWORD, "exec_entry", "offset of entrypoint");
struct.add(DWORD, "exec_flags", "loader flags");
struct.add(DWORD, "exec_bfill", "bss initialization value");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,160 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code export_entry} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomExportEntry implements StructConverter {
/** The size in bytes of a {@link SomExportEntry} */
public static final int SIZE = 0x14;
private int next;
private String name;
private int value;
private int info;
private int type;
private boolean isTpRelative;
private int reserved1;
private short moduleIndex;
/**
* Creates a new {@link SomExportEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the export list
* @param stringTableLoc The location of the string table
* @throws IOException if there was an IO-related error
*/
public SomExportEntry(BinaryReader reader, long stringTableLoc) throws IOException {
next = reader.readNextInt();
int nameIndex = reader.readNextInt();
name = nameIndex != -1 ? reader.readAsciiString(stringTableLoc + nameIndex) : null;
value = reader.readNextInt();
info = reader.readNextInt();
type = reader.readNextUnsignedByte();
int bitfield = reader.readNextUnsignedByte();
reserved1 = bitfield & 0x7f;
isTpRelative = ((bitfield >> 7) & 0x1) != 0;
moduleIndex = reader.readNextShort();
}
/**
* {@return the next export record in the hash chain}
*/
public int getNext() {
return next;
}
/**
* {@return the symbol name}
*/
public String getName() {
return name;
}
/**
* {@return the symbol address (subject to relocation)}
*/
public int getValue() {
return value;
}
/**
* {@return the size of the storage request if exported symbol is of type {@code STORAGE}, or
* the version of the exported symbol along with argument relocation information}
*/
public int getInfo() {
return info;
}
/**
* {@return the symbol type}
*
* @see SomConstants
*/
public int getType() {
return type;
}
/**
* {@return whether or not this is a TLS export}
*/
public boolean isTpRelative() {
return isTpRelative;
}
/**
* {@return the first reserved value}
*/
public int getReserved1() {
return reserved1;
}
/**
* {@return the index into the module table of the module defining this symbol}
*/
public short getModuleIndex() {
return moduleIndex;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType miscInfoStruct = new StructureDataType("misc_info", 4);
miscInfoStruct.setPackingEnabled(true);
miscInfoStruct.add(WORD, "version", "months since January, 1990");
try {
miscInfoStruct.addBitField(WORD, 6, "reserved2", null);
miscInfoStruct.addBitField(WORD, 10, "arg_reloc", "parameter relocation bits (5*2)");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
miscInfoStruct.setCategoryPath(new CategoryPath("/SOM"));
UnionDataType infoUnion = new UnionDataType("info");
infoUnion.add(DWORD, "size", "storage request area size in bytes");
infoUnion.add(miscInfoStruct, "misc", "version, etc. N/A to storage requests");
infoUnion.setCategoryPath(new CategoryPath("/SOM"));
StructureDataType struct = new StructureDataType("export_entry", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "next", "index of next export entry in hash chain");
struct.add(DWORD, "name", "offset within string table");
struct.add(DWORD, "value", "offset of symbol (subject to relocation)");
struct.add(infoUnion, "info", null);
struct.add(BYTE, "type", "symbol type");
try {
struct.addBitField(BYTE, 1, "is_tp_relative", "TLS export");
struct.addBitField(BYTE, 7, "reserved1", "reserved");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(WORD, "module_index", "index of module defining symbol");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,103 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code export_entry_ext} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomExportEntryExt implements StructConverter {
/** The size in bytes of a {@link SomExportEntryExt} */
public static final int SIZE = 0x14;
private int size;
private int dreloc;
private int sameList;
private int reserved2;
private int reserved3;
/**
* Creates a new {@link SomExportEntryExt}
*
* @param reader A {@link BinaryReader} positioned at the start of the export extension list
* @throws IOException if there was an IO-related error
*/
public SomExportEntryExt(BinaryReader reader) throws IOException {
size = reader.readNextInt();
dreloc = reader.readNextInt();
sameList = reader.readNextInt();
reserved2 = reader.readNextInt();
reserved3 = reader.readNextInt();
}
/**
* {@return the size of the export symbol and is only valid for exports of type {@code ST_DATA}
*/
public int getSize() {
return size;
}
/**
* {@return the start of the dreloc records for the exported symbol}
*/
public int getDreloc() {
return dreloc;
}
/**
* {@return the circular list of exports that have the same value (physical location) in the
* library}
*/
public int getSameList() {
return sameList;
}
/**
* {@return the second reserved value}
*/
public int getReserved2() {
return reserved2;
}
/**
* {@return the third reserved value}
*/
public int getReserved3() {
return reserved3;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("export_entry_ext", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "size", "export symbol size, data only");
struct.add(DWORD, "dreloc", "start of dreloc for this symbol");
struct.add(DWORD, "same_list", "circular list of exports that have the same value");
struct.add(DWORD, "reserved2", null);
struct.add(DWORD, "reserved3", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,605 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import static ghidra.app.util.bin.format.som.SomConstants.*;
import static ghidra.program.model.data.DataUtilities.ClearDataMode.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.CommentType;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* Represents a SOM {@code header} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomHeader implements StructConverter {
/** The size in bytes of a {@link SomHeader} */
public static final int SIZE = 0x80;
private int systemId;
private int magic;
private long versionId;
private SomSysClock fileTime;
private long entrySpace;
private long entrySubspace;
private long entryOffset;
private long auxHeaderLocation;
private long auxHeaderSize;
private long somLength;
private long presumedDp;
private long spaceLocation;
private long spaceTotal;
private long subspaceLocation;
private long subspaceTotal;
private long loaderFixupLocation;
private long loaderFixupTotal;
private long spaceStringsLocation;
private long spaceStringsSize;
private long initArrayLocation;
private long initArrayTotal;
private long compilerLocation;
private long compilerTotal;
private long symbolLocation;
private long symbolTotal;
private long fixupRequestLocation;
private long fixupRequestTotal;
private long symbolStringsLocation;
private long symbolStringsSize;
private long unloadableSpLocation;
private long unloadableSpSize;
private long checksum;
private List<SomSpace> spaces = new ArrayList<>();
private List<SomSubspace> subspaces = new ArrayList<>();
private List<SomAuxHeader> auxHeaders = new ArrayList<>();
private List<SomCompilationUnit> compilationUnits = new ArrayList<>();
private List<SomSymbol> symbols = new ArrayList<>();
/**
* Creates a new {@link SomHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the header
* @throws IOException if there was an IO-related error
*/
public SomHeader(BinaryReader reader) throws IOException {
systemId = reader.readNextUnsignedShort();
magic = reader.readNextUnsignedShort();
versionId = reader.readNextUnsignedInt();
fileTime = new SomSysClock(reader);
entrySpace = reader.readNextUnsignedInt();
entrySubspace = reader.readNextUnsignedInt();
entryOffset = reader.readNextUnsignedInt();
auxHeaderLocation = reader.readNextUnsignedInt();
auxHeaderSize = reader.readNextUnsignedInt();
somLength = reader.readNextUnsignedInt();
presumedDp = reader.readNextUnsignedInt();
spaceLocation = reader.readNextUnsignedInt();
spaceTotal = reader.readNextUnsignedInt();
subspaceLocation = reader.readNextUnsignedInt();
subspaceTotal = reader.readNextUnsignedInt();
loaderFixupLocation = reader.readNextUnsignedInt();
loaderFixupTotal = reader.readNextUnsignedInt();
spaceStringsLocation = reader.readNextUnsignedInt();
spaceStringsSize = reader.readNextUnsignedInt();
initArrayLocation = reader.readNextUnsignedInt();
initArrayTotal = reader.readNextUnsignedInt();
compilerLocation = reader.readNextUnsignedInt();
compilerTotal = reader.readNextUnsignedInt();
symbolLocation = reader.readNextUnsignedInt();
symbolTotal = reader.readNextUnsignedInt();
fixupRequestLocation = reader.readNextUnsignedInt();
fixupRequestTotal = reader.readNextUnsignedInt();
symbolStringsLocation = reader.readNextUnsignedInt();
symbolStringsSize = reader.readNextUnsignedInt();
unloadableSpLocation = reader.readNextUnsignedInt();
unloadableSpSize = reader.readNextUnsignedInt();
checksum = reader.readNextUnsignedInt();
if (spaceLocation > 0) {
reader.setPointerIndex(spaceLocation);
for (int i = 0; i < spaceTotal; i++) {
spaces.add(new SomSpace(reader, spaceStringsLocation));
}
}
if (subspaceLocation > 0) {
reader.setPointerIndex(subspaceLocation);
for (int i = 0; i < subspaceTotal; i++) {
subspaces.add(new SomSubspace(reader, spaceStringsLocation));
}
}
if (auxHeaderLocation > 0) {
reader.setPointerIndex(auxHeaderLocation);
long sizeRemaining = auxHeaderSize;
while (sizeRemaining > 0) {
SomAuxHeader auxHeader = SomAuxHeaderFactory.readNextAuxHeader(reader);
auxHeaders.add(auxHeader);
sizeRemaining -= auxHeader.getAuxId().getLength() + SomAuxId.SIZE;
}
}
if (compilerLocation > 0) {
reader.setPointerIndex(compilerLocation);
for (int i = 0; i < compilerTotal; i++) {
compilationUnits.add(new SomCompilationUnit(reader, symbolStringsLocation));
}
}
if (symbolLocation > 0) {
reader.setPointerIndex(symbolLocation);
for (int i = 0; i < symbolTotal; i++) {
symbols.add(new SomSymbol(reader, symbolStringsLocation));
}
}
}
/**
* {@return the system ID}
*/
public int getSystemId() {
return systemId;
}
/**
* {@return the magic}
*/
public int getMagic() {
return magic;
}
/**
* {@return true if this {@link SomHeader} has a valid magic number; otherwise false}
*/
public boolean hasValidMagic() {
return switch (magic) {
case MAGIC_LIBRARY:
case MAGIC_RELOCATABLE:
case MAGIC_NON_SHAREABLE_EXE:
case MAGIC_SHAREABLE_EXE:
case MAGIC_SHARABLE_DEMAND_LOADABLE_EXE:
case MAGIC_DYNAMIC_LOAD_LIBRARY:
case MAGIC_SHARED_LIBRARY:
case MAGIC_RELOCATABLE_LIBRARY:
yield true;
default:
yield false;
};
}
/**
* {@return the version ID}
*/
public long getVersionId() {
return versionId;
}
/**
* {@return true if this {@link SomHeader} has a valid version ID; otherwise false}
*/
public boolean hasValidVersionId() {
return versionId == 85082112 || versionId == 87102412;
}
/**
* {@return the file time}
*/
public SomSysClock getFileType() {
return fileTime;
}
/**
* {@return the index of space containing entry point}
*/
public long getEntrySpace() {
return entrySpace;
}
/**
* {@return the index of subspace for entry point}
*/
public long getEntrySubspace() {
return entrySubspace;
}
/**
* {@return the offset of entry point}
*/
public long getEntryOffset() {
return entryOffset;
}
/**
* {@return the auxiliary header location}
*/
public long getAuxHeaderLocation() {
return auxHeaderLocation;
}
/**
* {@return the auxiliary header size}
*/
public long getAuxHeaderSize() {
return auxHeaderSize;
}
/**
* {@return the length in bytes of entire som}
*/
public long getSomLength() {
return somLength;
}
/**
* {@return the DP value assumed during compilation}
*/
public long getPresumedDp() {
return presumedDp;
}
/**
* {@return the location in file of space dictionary}
*/
public long getSpaceLocation() {
return spaceLocation;
}
/**
* {@return the number of space entries}
*/
public long getSpaceTotal() {
return spaceTotal;
}
/**
* {@return the location of subspace entries}
*/
public long getSubspaceLocation() {
return subspaceLocation;
}
/**
* {@return the number of subspace entries}
*/
public long getSubspaceTotal() {
return subspaceTotal;
}
/**
* {@return the MPE/iX loader fixup location}
*/
public long getLoaderFixupLocation() {
return loaderFixupLocation;
}
/**
* {@return the number of loader fixup records}
*/
public long getLoaderFixupTotal() {
return loaderFixupTotal;
}
/**
* {@return the file location of string area for space and subspace names}
*/
public long getSpaceStringsLocation() {
return spaceStringsLocation;
}
/**
* {@return the size of string area for space and subspace names}
*/
public long getSpaceStringsSize() {
return spaceStringsSize;
}
/**
* {@return the init array location}
*/
public long getInitArrayLocation() {
return initArrayLocation;
}
/**
* {@return the init array total}
*/
public long getInitArrayTotal() {
return initArrayTotal;
}
/**
* {@return the location in file of module dictionary}
*/
public long getCompilerLocation() {
return compilerLocation;
}
/**
* {@return the number of modules}
*/
public long getCompilerTotal() {
return compilerTotal;
}
/**
* {@return the location in file of symbol dictionary}
*/
public long getSymbolLocation() {
return symbolLocation;
}
/**
* {@return the number of symbol records}
*/
public long getSymbolTotal() {
return symbolTotal;
}
/**
* {@return the location in file of fixup requests}
*/
public long getFixupRequestLocation() {
return fixupRequestLocation;
}
/**
* {@return the number of fixup requests}
*/
public long getFixupRequestTotal() {
return fixupRequestTotal;
}
/**
* {@return the file location of string area for module and symbol names}
*/
public long getSymbolStringsLocation() {
return symbolStringsLocation;
}
/**
* {@return the size of string area for module and symbol names}
*/
public long getSymbolStringsSize() {
return symbolStringsSize;
}
/**
* {@return the byte offset of first byte of data for unloadable spaces}
*/
public long getUnloadableSpLocation() {
return unloadableSpLocation;
}
/**
* {@return the byte length of data for unloadable spaces}
*/
public long getUnloadableSpSize() {
return unloadableSpSize;
}
/**
* {@return the checksum}
*/
public long getChecksum() {
return checksum;
}
/**
* {@return the {@link List} of {@link SomSpace spaces}}
*/
public List<SomSpace> getSpaces() {
return new ArrayList<>(spaces);
}
/**
* {@return the {@link List} of {@link SomSubspace subspaces}}
*/
public List<SomSubspace> getSubspaces() {
return subspaces;
}
/**
* {@return the {@link List} of {@link SomAuxHeader auxiliary headers}}
*/
public List<SomAuxHeader> getAuxHeaders() {
return auxHeaders;
}
/**
* {@return the {@link List} of {@link SomAuxHeader auxiliary headers}} of the given type}
*
* @param <T> The type of auxiliary header to get
* @param classType The type of auxiliary header to get
*/
public <T> List<T> getAuxHeaders(Class<T> classType) {
List<T> tmp = new ArrayList<>();
for (SomAuxHeader auxHeader : auxHeaders) {
if (classType.isAssignableFrom(auxHeader.getClass())) {
tmp.add(classType.cast(auxHeader));
}
}
return tmp;
}
/**
* {@return the first found {@link SomAuxHeader auxiliary header}} of the given type}
*
* @param <T> The type of auxiliary header to get
* @param classType The type of auxiliary header to get
*/
public <T> T getFirstAuxHeader(Class<T> classType) {
for (SomAuxHeader auxHeader : auxHeaders) {
if (classType.isAssignableFrom(auxHeader.getClass())) {
return classType.cast(auxHeader);
}
}
return null;
}
/**
* {@return the {@link List} of {@link SomCompilationUnit compilation units}}
*/
public List<SomCompilationUnit> getCompilationUnits() {
return compilationUnits;
}
/**
* {@return the {@link List} of {@link SomSymbol symbols}}
*/
public List<SomSymbol> getSymbols() {
return symbols;
}
/**
* {@return the starting address of the "text" space}
*
* @param program The {@link Program}
* @throws Exception if there was a problem getting the address
*/
public Address getTextAddress(Program program) throws Exception {
// Assuming that the text space is the first space
return program.getAddressFactory()
.getDefaultAddressSpace()
.getAddress(subspaces.get(spaces.get(0).getSubspaceIndex()).getSubspaceStart());
}
/**
* {@return the starting address of the "data" space, or {@code null} if it wasn't found}
*
* @param program The {@link Program}
* @throws Exception if there was a problem getting the address
*/
public Address getDataAddress(Program program) throws Exception {
// Assuming that the text space is the second space
return program.getAddressFactory()
.getDefaultAddressSpace()
.getAddress(subspaces.get(spaces.get(1).getSubspaceIndex()).getSubspaceStart());
}
/**
* Marks up this header
*
* @param program The {@link Program}
* @param headerAddr The {@link Address} of this header
* @param monitor A cancellable monitor
* @throws Exception if there was a problem during markup
*/
public void markup(Program program, Address headerAddr, TaskMonitor monitor) throws Exception {
DataUtilities.createData(program, headerAddr, toDataType(), -1, CHECK_FOR_SPACE);
monitor.initialize(spaceTotal, "Marking up spaces...");
for (int i = 0; i < spaceTotal; i++) {
monitor.increment();
SomSpace space = spaces.get(i);
Address addr = headerAddr.add(spaceLocation + i * SomSpace.SIZE);
DataUtilities.createData(program, addr, space.toDataType(), -1, CHECK_FOR_SPACE);
program.getListing().setComment(addr, CommentType.EOL, space.getName());
}
monitor.initialize(subspaceTotal, "Marking up subspaces...");
for (int i = 0; i < subspaceTotal; i++) {
monitor.increment();
SomSubspace subspace = subspaces.get(i);
Address addr = headerAddr.add(subspaceLocation + i * SomSubspace.SIZE);
DataUtilities.createData(program, addr, subspace.toDataType(), -1, CHECK_FOR_SPACE);
program.getListing().setComment(addr, CommentType.EOL, subspace.getName());
}
monitor.initialize(auxHeaders.size(), "Marking up auxiliary headers...");
Address auxHeaderAddr = headerAddr.add(auxHeaderLocation);
for (SomAuxHeader auxHeader : auxHeaders) {
monitor.increment();
DataUtilities.createData(program, auxHeaderAddr, auxHeader.toDataType(), -1,
CHECK_FOR_SPACE);
auxHeaderAddr = auxHeaderAddr.add(auxHeader.getLength());
}
monitor.initialize(compilerTotal, "Marking up compilation units...");
for (int i = 0; i < compilerTotal; i++) {
monitor.increment();
SomCompilationUnit unit = compilationUnits.get(i);
Address addr = headerAddr.add(compilerLocation + i * SomCompilationUnit.SIZE);
DataUtilities.createData(program, addr, unit.toDataType(), -1, CHECK_FOR_SPACE);
program.getListing().setComment(addr, CommentType.EOL, unit.getName());
}
monitor.initialize(symbolTotal, "Marking up symbols...");
for (int i = 0; i < symbolTotal; i++) {
monitor.increment();
SomSymbol symbol = symbols.get(i);
Address addr = headerAddr.add(symbolLocation + i * SomSymbol.SIZE);
DataUtilities.createData(program, addr, symbol.toDataType(), -1, CHECK_FOR_SPACE);
program.getListing().setComment(addr, CommentType.EOL, symbol.getName());
}
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("header", SIZE);
struct.setPackingEnabled(true);
struct.add(WORD, "system_id", "magic number - system");
struct.add(WORD, "a_magic", "magic number - file type");
struct.add(DWORD, "version_id", "version id; format=YYMMDDHH");
struct.add(fileTime.toDataType(), "file_time", "system clock- zero if unused");
struct.add(DWORD, "entry_space", "index of space containing entry point");
struct.add(DWORD, "entry_subspace", "index of subspace for entry point");
struct.add(DWORD, "entry_offset", "offset of entry point");
struct.add(DWORD, "aux_header_location", "auxiliary header location");
struct.add(DWORD, "aux_header_size", "auxiliary header size");
struct.add(DWORD, "som_length", "length in bytes of entire som");
struct.add(DWORD, "presumed_dp", "DP value assumed during compilation");
struct.add(DWORD, "space_location", "location in file of space dictionary");
struct.add(DWORD, "space_total", "number of space entries");
struct.add(DWORD, "subspace_location", "location of subspace entries");
struct.add(DWORD, "subspace_total", "number of subspace entries");
struct.add(DWORD, "loader_fixup_location", "MPE/iX loader fixup");
struct.add(DWORD, "loader_fixup_total", "number of loader fixup records");
struct.add(DWORD, "space_strings_location",
"file location of string area for space and subspace names");
struct.add(DWORD, "space_strings_size", "size of string area for space and subspace names");
struct.add(DWORD, "init_array_location", "reserved for use by system");
struct.add(DWORD, "init_array_total", "reserved for use by system");
struct.add(DWORD, "compiler_location", "location in file of module dictionary");
struct.add(DWORD, "compiler_total", "number of modules");
struct.add(DWORD, "symbol_location", "location in file of symbol dictionary");
struct.add(DWORD, "symbol_total", "number of symbol records");
struct.add(DWORD, "fixup_request_location", "location in file of fixup requests");
struct.add(DWORD, "fixup_request_total", "number of fixup requests");
struct.add(DWORD, "symbol_strings_location",
"file location of string area for module and symbol names");
struct.add(DWORD, "symbol_strings_size", "size of string area for module and symbol names");
struct.add(DWORD, "unloadable_sp_location",
"byte offset of first byte of data for unloadable spaces");
struct.add(DWORD, "unloadable_sp_size", "byte length of data for unloadable spaces");
struct.add(DWORD, "checksum", "");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,110 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code import_entry} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomImportEntry implements StructConverter {
/** The size in bytes of a {@link SomImportEntry} */
public static final int SIZE = 0x8;
private String name;
private int reserved2;
private int type;
private boolean bypassable;
private int reserved1;
/**
* Creates a new {@link SomImportEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the import list
* @param stringTableLoc The location of the string table
* @throws IOException if there was an IO-related error
*/
public SomImportEntry(BinaryReader reader, long stringTableLoc) throws IOException {
int nameIndex = reader.readNextInt();
name = nameIndex != -1 ? reader.readAsciiString(stringTableLoc + nameIndex) : null;
int bitfield = reader.readNextInt();
reserved1 = bitfield & 0x7f;
bypassable = ((bitfield >> 7) & 0x1) != 0;
type = (bitfield >> 8) & 0xff;
reserved2 = (bitfield >> 16) & 0xffff;
}
/**
* {@return the name of the import, or {@code null} if it doesn't have one}
*/
public String getName() {
return name;
}
/**
* {@return the second reserved value}
*/
public int getReserved2() {
return reserved2;
}
/**
* {@return the symbol type (text, data, or bss)}
*/
public int getType() {
return type;
}
/**
* {@return whether or not code imports do not have their address taken in that shared library}
*/
public boolean isBypassable() {
return bypassable;
}
/**
* {@return the first reserved value}
*/
public int getReserved1() {
return reserved1;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("import_entry", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "name", "offset in string table");
try {
struct.addBitField(DWORD, 16, "reserved2", "unused");
struct.addBitField(DWORD, 8, "type", "symbol type");
struct.addBitField(DWORD, 1, "bypassable", "address of code symbol not taken in shlib");
struct.addBitField(DWORD, 7, "reserved1", "unused");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,81 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code linker_footprint} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomLinkerFootprintAuxHeader extends SomAuxHeader {
private String productId;
private String versionId;
private SomSysClock htime;
/**
* Creates a new {@link SomLinkerFootprintAuxHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary header
* @throws IOException if there was an IO-related error
*/
public SomLinkerFootprintAuxHeader(BinaryReader reader) throws IOException {
super(reader);
productId = reader.readNextAsciiString(12);
versionId = reader.readNextAsciiString(12);
htime = new SomSysClock(reader);
}
/**
* {@return the product ID}
*/
public String getProductId() {
return productId;
}
/**
* {@return the version ID}
*/
public String getVersionId() {
return versionId;
}
/**
* {@return the htime}
*/
public SomSysClock getHtime() {
return htime;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("linker_footprint", 0);
struct.setPackingEnabled(true);
struct.add(auxId.toDataType(), "som_auxhdr", null);
struct.add(STRING, 12, "product_id", null);
struct.add(STRING, 8, "version_id", null);
struct.add(htime.toDataType(), "htime", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,123 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code module_entry} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomModuleEntry implements StructConverter {
/** The size in bytes of a {@link SomModuleEntry} */
public static final int SIZE = 0x14;
private int drelocs;
private int imports;
private int importCount;
private int flags;
private int reserved1;
private int moduleDependencies;
private int reserved2;
/**
* Creates a new {@link SomModuleEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the module list
* @throws IOException if there was an IO-related error
*/
public SomModuleEntry(BinaryReader reader) throws IOException {
drelocs = reader.readNextInt();
imports = reader.readNextInt();
importCount = reader.readNextInt();
flags = reader.readNextUnsignedByte();
reserved1 = reader.readNextUnsignedByte();
moduleDependencies = reader.readNextUnsignedShort();
reserved2 = reader.readNextInt();
}
/**
* {@return the text address into the dynamic relocation table}
*/
public int getDrelocs() {
return drelocs;
}
/**
* {@return the text address into the module import table}
*/
public int getImports() {
return imports;
}
/**
* {@return the number of symbol entries in the module import table belonging to this module}
*/
public int getImportCount() {
return importCount;
}
/**
* {@return the flags}
*/
public int getFlags() {
return flags;
}
/**
* {@return the first reserved value}
*/
public int getReserved1() {
return reserved1;
}
/**
* {@return the number of modules the current module needs to have bound before all of its own
* import symbols can be found}
*/
public int getModuleDependencies() {
return moduleDependencies;
}
/**
* {@return the second reserved value}
*/
public int getReserved2() {
return reserved2;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("module_entry", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "drelocs", "text offset into module dynamic relocation array");
struct.add(DWORD, "imports", "text offset into module import array");
struct.add(DWORD, "imports_count", "number of entries into module import array");
struct.add(BYTE, "flags", "currently flags defined: ELAB_REF");
struct.add(BYTE, "reserved1", null);
struct.add(WORD, "module_dependencies", null);
struct.add(DWORD, "reserved2", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,72 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code PLT_entry} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomPltEntry implements StructConverter {
/** The size in bytes of a {@link SomPltEntry} */
public static final int SIZE = 0x8;
private int procAddr;
private int ltptrValue;
/**
* Creates a new {@link SomPltEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the PLT
* @throws IOException if there was an IO-related error
*/
public SomPltEntry(BinaryReader reader) throws IOException {
procAddr = reader.readNextInt();
ltptrValue = reader.readNextInt();
}
/**
* {@return the address of the procedure to be branched to}
*/
public int getProcAddr() {
return procAddr;
}
/**
* {@return the import index of the code symbol (if {@code proc_addr} points to the BOR routine}
*/
public int getLtptrValue() {
return ltptrValue;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("PLT_entry", SIZE);
struct.setPackingEnabled(true);
struct.add(POINTER, "poc_addr", "address of procedure");
struct.add(DWORD, "ltptr_value", "value of r19 required for this procedure");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,61 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM "product specifics" structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomProductSpecificsAuxHeader extends SomAuxHeader {
private byte[] bytes;
/**
* Creates a new {@link SomProductSpecificsAuxHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary header
* @throws IOException if there was an IO-related error
*/
public SomProductSpecificsAuxHeader(BinaryReader reader) throws IOException {
super(reader);
bytes = reader.readNextByteArray((int) auxId.getLength());
}
/**
* {@return the product specific bytes}
*/
public byte[] getBytes() {
return bytes;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("som_product_specifics_auxhdr", 0);
struct.setPackingEnabled(true);
struct.add(auxId.toDataType(), "som_auxhdr", null);
struct.add(new ArrayDataType(BYTE, (int) auxId.getLength(), 1), "bytes", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,121 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code shlib_list_entry} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomShlibListEntry implements StructConverter {
/** The size in bytes of a {@link SomShlibListEntry} */
public static final int SIZE = 0x8;
private String shlibName;
private int reserved1;
private boolean internalName;
private boolean dashLReference;
private int bind;
private short highwaterMark;
/**
* Creates a new {@link SomShlibListEntry}
*
* @param reader A {@link BinaryReader} positioned at the start of the header
* @param stringTableLoc The location of the string table
* @throws IOException if there was an IO-related error
*/
public SomShlibListEntry(BinaryReader reader, long stringTableLoc) throws IOException {
shlibName = reader.readAsciiString(stringTableLoc + reader.readNextInt());
int bitfield = reader.readNextUnsignedByte();
dashLReference = (bitfield & 0x1) != 0;
internalName = ((bitfield >> 1) & 0x1) != 0;
reserved1 = (bitfield >> 2) & 0x3f;
bind = reader.readNextUnsignedByte();
highwaterMark = reader.readNextShort();
}
/**
* {@return the name of the shared library}
*/
public String getShlibName() {
return shlibName;
}
/**
* {@return the reserved value}
*/
public int getReserved1() {
return reserved1;
}
/**
* {@return whether or not the shared library entry is an internal name}
*/
public boolean isInternalName() {
return internalName;
}
/**
* {@return whether or not the shared library was specified on the link line with
* the {@code -l} option or not}
*/
public boolean getDashLReference() {
return dashLReference;
}
/**
* {@return the binding-time preference}
*/
public int getBind() {
return bind;
}
/**
* {@return the {@code highwater_mark} value}
*/
public short getHighwaterMark() {
return highwaterMark;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("shlib_list_entry", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "shlib_name", "offset withing string table");
try {
struct.addBitField(BYTE, 6, "reserved1", "");
struct.addBitField(BYTE, 1, "internal_name", "shlib entry is an internal name");
struct.addBitField(BYTE, 1, "dash_l_reference", "referenced with -lc or absolute path");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(BYTE, "bind", "BIND_IMMEDIATE, BIND_DEFERRED or BIND_REFERENCE");
struct.add(WORD, "highwater_mark", "highwater mark of the library");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,222 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code space_dictionary_record} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomSpace implements StructConverter {
/** The size in bytes of a {@link SomSpace} */
public static final int SIZE = 0x24;
private String name;
private boolean isLoadable;
private boolean isDefined;
private boolean isPrivate;
private boolean hasIntermediateCode;
private boolean isThreadSpecific;
private int reserved;
private int sortKey;
private int reserved2;
private int spaceNumber;
private int subspaceIndex;
private long subspaceQuantity;
private int loaderFixIndex;
private long loaderFixQuantity;
private int initPointerIndex;
private long initPointerQuantity;
/**
* Creates a new {@link SomSpace}
*
* @param reader A {@link BinaryReader} positioned at the start of the record
* @param spaceStringsLocation The starting index of the space strings
* @throws IOException if there was an IO-related error
*/
public SomSpace(BinaryReader reader, long spaceStringsLocation) throws IOException {
name = reader.readAsciiString(spaceStringsLocation + reader.readNextUnsignedInt());
int bitfield = reader.readNextInt();
reserved2 = bitfield & 0xff;
sortKey = (bitfield >> 8) & 0xff;
reserved = (bitfield >> 16) & 0x7ff;
isThreadSpecific = ((bitfield >> 27) & 0x1) != 0;
hasIntermediateCode = ((bitfield >> 28) & 0x1) != 0;
isPrivate = ((bitfield >> 29) & 0x1) != 0;
isDefined = ((bitfield >> 30) & 0x1) != 0;
isLoadable = ((bitfield >> 31) & 0x1) != 0;
spaceNumber = reader.readNextInt();
subspaceIndex = reader.readNextInt();
subspaceQuantity = reader.readNextUnsignedInt();
loaderFixIndex = reader.readNextInt();
loaderFixQuantity = reader.readNextUnsignedInt();
initPointerIndex = reader.readNextInt();
initPointerQuantity = reader.readNextUnsignedInt();
}
/**
* {@return the space name}
*/
public String getName() {
return name;
}
/**
* {@return whether or not the space is loadable}
*/
public boolean isLoadable() {
return isLoadable;
}
/**
* {@return whether or not the space is defined within the file}
*/
public boolean isDefined() {
return isDefined;
}
/**
* {@return whether or not the space is not sharable}
*/
public boolean isPrivate() {
return isPrivate;
}
/**
* {@return whether or not the space contains intermediate code}
*/
public boolean hasIntermediateCode() {
return hasIntermediateCode;
}
/**
* {@return whether or not the space is thread specific}
*/
public boolean isThreadSpecific() {
return isThreadSpecific;
}
/**
* {@return the first reserved value}
*/
public int getReserved() {
return reserved;
}
/**
* {@return the sort key for the space}
*/
public int getSortKey() {
return sortKey;
}
/**
* {@return the second reserved value}
*/
public int getReserved2() {
return reserved2;
}
/**
* {@return the space index}
*/
public int getSpaceNumber() {
return spaceNumber;
}
/**
* {@return the index into the subspace dictionary}
*/
public int getSubspaceIndex() {
return subspaceIndex;
}
/**
* {@return the number of subspaces in the space}
*/
public long getSubspaceQuantity() {
return subspaceQuantity;
}
/**
* {@return the load fix index}
*/
public int getLoaderFixIndex() {
return loaderFixIndex;
}
/**
* {@return the load fix quantity}
*/
public long getLoaderFixQuantity() {
return loaderFixQuantity;
}
/**
* {@return the index into data (init) pointer array}
*/
public int getInitPonterIndex() {
return initPointerIndex;
}
/**
* {@return the number of data (init) pointers}
*/
public long getInitPointerQuantity() {
return initPointerQuantity;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct =
new StructureDataType("space_dictionary_record", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "name", "index to subspace name");
try {
struct.addBitField(DWORD, 1, "is_loadable", "space is loadable");
struct.addBitField(DWORD, 1, "is_defined", "space is defined within file");
struct.addBitField(DWORD, 1, "is_private", "space is not sharable");
struct.addBitField(DWORD, 1, "has_intermediate_code", "contain intermediate code");
struct.addBitField(DWORD, 1, "is_tspecific", "is thread specific");
struct.addBitField(DWORD, 11, "reserved", "reserved for future expansion");
struct.addBitField(DWORD, 8, "sort_key", "sort key for space");
struct.addBitField(DWORD, 8, "reserved2", "reserved for future expansion");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "space_number", "space index");
struct.add(DWORD, "subspace_index", "index into subspace dictionary");
struct.add(DWORD, "subspace_quantity", "number of subspaces in space");
struct.add(DWORD, "loader_fix_index", "loader usage");
struct.add(DWORD, "loader_fix_quantity", "loader usage");
struct.add(DWORD, "init_pointer_index", "index into data(initialization) pointer array");
struct.add(DWORD, "init_pointer_quantity", "number of data (init) pointers");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,348 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code subspace_dictionary_record} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomSubspace implements StructConverter {
/** The size in bytes of a {@link SomSubspace} */
public static final int SIZE = 0x28;
private int spaceIndex;
private int accessControlBits;
private boolean memoryResident;
private boolean dupCommon;
private boolean isCommon;
private boolean isLoadable;
private int quadrant;
private boolean initiallyFrozen;
private boolean isFirst;
private boolean codeOnly;
private int sortKey;
private boolean replicateInit;
private boolean continuation;
private boolean isThreadSpecific;
private boolean isComdat;
private int reserved;
private int fileLocInitValue;
private long initializationLength;
private long subspaceStart;
private long subspaceLength;
private int reserved2;
private int alignment;
private String name;
private int fixupRequestIndex;
private long fixupRequestQuantity;
/**
* Creates a new {@link SomSubspace}
*
* @param reader A {@link BinaryReader} positioned at the start of the record
* @param spaceStringsLocation The starting index of the space strings
* @throws IOException if there was an IO-related error
*/
public SomSubspace(BinaryReader reader, long spaceStringsLocation) throws IOException {
spaceIndex = reader.readNextInt();
int bitfield = reader.readNextInt();
reserved = bitfield & 0x0f;
isComdat = ((bitfield >> 4) & 0x1) != 0;
isThreadSpecific = ((bitfield >> 5) & 0x1) != 0;
continuation = ((bitfield >> 6) & 0x1) != 0;
replicateInit = ((bitfield >> 7) & 0x1) != 0;
sortKey = (bitfield >> 8) & 0xff;
codeOnly = ((bitfield >> 16) & 0x1) != 0;
isFirst = ((bitfield >> 17) & 0x1) != 0;
initiallyFrozen = ((bitfield >> 18) & 0x1) != 0;
quadrant = (bitfield >> 19) & 0x3;
isLoadable = ((bitfield >> 21) & 0x1) != 0;
isCommon = ((bitfield >> 22) & 0x1) != 0;
dupCommon = ((bitfield >> 23) & 0x1) != 0;
memoryResident = ((bitfield >> 24) & 0x1) != 0;
accessControlBits = (bitfield >> 25) & 0x7f;
fileLocInitValue = reader.readNextInt();
initializationLength = reader.readNextUnsignedInt();
subspaceStart = reader.readNextUnsignedInt();
subspaceLength = reader.readNextUnsignedInt();
bitfield = reader.readNextInt();
alignment = bitfield & 0x7ffffff;
reserved2 = (bitfield >> 27) & 0x1f;
name = reader.readAsciiString(spaceStringsLocation + reader.readNextUnsignedInt());
fixupRequestIndex = reader.readNextInt();
fixupRequestQuantity = reader.readNextUnsignedInt();
}
/**
* {@return the space index}
*/
public int getSpaceIndex() {
return spaceIndex;
}
/**
* {@return the access control bits for PDIR entries}
*/
public int getAccessControlBits() {
return accessControlBits;
}
/**
* {@return whether or not to lock in memory during execution}
*/
public boolean isMemoryResident() {
return memoryResident;
}
/**
* {@return whether or not data name clashes are allowed}
*/
public boolean isDupCommon() {
return dupCommon;
}
/**
* {@return whether or not the subspace is a common}
*/
public boolean isCommon() {
return isCommon;
}
/**
* {@return whether or not the subspace is loadable}
*/
public boolean isLoadable() {
return isLoadable;
}
/**
* {@return the quadrant request}
*/
public int getQuadrant() {
return quadrant;
}
/**
* {@return whether or not the subspace must be locked into memory when the OS is booted}
*/
public boolean isInitiallyFrozen() {
return initiallyFrozen;
}
/**
* {@return whether or not this must be the first subspace}
*/
public boolean isFirst() {
return isFirst;
}
/**
* {@return whether or not the subspace must contain only code}
*/
public boolean isCodeOnly() {
return codeOnly;
}
/**
* {@return the sort key for the subspace}
*/
public int getSortKey() {
return sortKey;
}
/**
* {@return whether or not init values are replicated to fill {@code subspace_length}}
*/
public boolean isReplicateInit() {
return replicateInit;
}
/**
* {@return whether or not this subspace is a continuation}
*/
public boolean isContinuation() {
return continuation;
}
/**
* {@return whether or not the subspace is thread specific}
*/
public boolean isThreadSpecific() {
return isThreadSpecific;
}
/**
* {@return whether or not this is for COMDAT subspaces}
*/
public boolean isComdat() {
return isComdat;
}
/**
* {@return the first reserved value}
*/
public int getReserved() {
return reserved;
}
/**
* {@return the file location or initialization value}
*/
public int getFileLocInitValue() {
return fileLocInitValue;
}
/**
* {@return the initialization length}
*/
public long getInitializationLength() {
return initializationLength;
}
/**
* {@return the starting offset}
*/
public long getSubspaceStart() {
return subspaceStart;
}
/**
* {@return the number of bytes defined by this subspace}
*/
public long getSubspaceLength() {
return subspaceLength;
}
/**
* {@return the second reserved value}
*/
public int getReserved2() {
return reserved2;
}
/**
* {@return the alignment required for the subspace}
*/
public int getAlignment() {
return alignment;
}
/**
* {@return the subspace name}
*/
public String getName() {
return name;
}
/**
* {@return the index into fixup array}
*/
public int getFixupRequestIndex() {
return fixupRequestIndex;
}
/**
* {@return the number of fixup requests}
*/
public long getFixupRequestQuantity() {
return fixupRequestQuantity;
}
/**
* {@return whether or not this subspace is readable}
*/
public boolean isRead() {
return getAccessControlType() < 4;
}
/**
* {@return whether or not this subspace is writeable}
*/
public boolean isWrite() {
return getAccessControlType() == 1 || getAccessControlType() == 3;
}
/**
* {@return whether or not this subspace is executable}
*/
public boolean isExecute() {
return getAccessControlType() >= 2;
}
/**
* {@return the "type" part of the access control bits}
*/
private int getAccessControlType() {
return (accessControlBits >> 4) & 0x3;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("subspace_dictionary_record", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "space_index", "");
try {
struct.addBitField(DWORD, 7, "access_control_bits", "access for PDIR entries");
struct.addBitField(DWORD, 1, "memory_resident", "lock in memory during execution");
struct.addBitField(DWORD, 1, "dup_common", "data name clashes allowed");
struct.addBitField(DWORD, 1, "is_common", "subspace is a common");
struct.addBitField(DWORD, 1, "is_loadable", "");
struct.addBitField(DWORD, 2, "quadrant", "quadrant request");
struct.addBitField(DWORD, 1, "initially_frozen",
"must be locked into memory when OS is booted");
struct.addBitField(DWORD, 1, "is_first", "must be first subspace");
struct.addBitField(DWORD, 1, "code_only", "must contain only code");
struct.addBitField(DWORD, 8, "sort_key", "subspace sort key");
struct.addBitField(DWORD, 1, "replicate_init",
"init values replicated to fill subspace_length");
struct.addBitField(DWORD, 1, "continuation", "subspace is a continuation");
struct.addBitField(DWORD, 1, "is_tspecific", "is thread specific?");
struct.addBitField(DWORD, 1, "is_comdat", "Is for COMDAT subspaces?");
struct.addBitField(DWORD, 4, "reserved", "");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "file_loc_init_value", "file location or initialization value");
struct.add(DWORD, "initialization_length", "");
struct.add(DWORD, "subspace_start", "starting offset");
struct.add(DWORD, "subspace_length", "number of bytes defined by this subspace");
try {
struct.addBitField(DWORD, 5, "reserved2", "");
struct.addBitField(DWORD, 27, "alignment",
"alignment required for the subspace (largest alignment requested for any item in the subspace)");
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "name", "index of subspace name");
struct.add(DWORD, "fixup_request_index", "index into fixup array");
struct.add(DWORD, "fixup_request_quantity", "number of fixup requests");
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,285 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code symbol_dictionary_record} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomSymbol implements StructConverter {
/** The size in bytes of a {@link SomSymbol} */
public static final int SIZE = 0x14;
private boolean hidden;
private boolean secondaryDef;
private int symbolType;
private int symbolScope;
private int checkLevel;
private boolean mustQualify;
private boolean initiallyFrozen;
private boolean memoryResident;
private boolean isCommon;
private boolean dupCommon;
private int xleast;
private int argReloc;
private String name;
private String qualifierName;
private boolean hasLongReturn;
private boolean noRelocation;
private boolean isComdat;
private int reserved;
private int symbolInfo;
private long symbolValue;
/**
* Creates a new {@link SomSymbol}
*
* @param reader A {@link BinaryReader} positioned at the start of the record
* @param symbolStringsLocation The starting index of the symbol strings
* @throws IOException if there was an IO-related error
*/
public SomSymbol(BinaryReader reader, long symbolStringsLocation) throws IOException {
int bitfield = reader.readNextInt();
argReloc = bitfield & 0x3ff;
xleast = (bitfield >> 10) & 0x3;
dupCommon = ((bitfield >> 12) & 0x1) != 0;
isCommon = ((bitfield >> 13) & 0x1) != 0;
memoryResident = ((bitfield >> 14) & 0x1) != 0;
initiallyFrozen = ((bitfield >> 15) & 0x1) != 0;
mustQualify = ((bitfield >> 16) & 0x1) != 0;
checkLevel = (bitfield >> 17) & 0x7;
symbolScope = (bitfield >> 20) & 0xf;
symbolType = (bitfield >> 24) & 0x3f;
secondaryDef = ((bitfield >> 30) & 0x1) != 0;
hidden = ((bitfield >> 31) & 0x1) != 0;
name = reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
qualifierName =
reader.readAsciiString(symbolStringsLocation + reader.readNextUnsignedInt());
bitfield = reader.readNextInt();
symbolInfo = bitfield & 0xffffff;
reserved = (bitfield >> 24) & 0x1f;
isComdat = ((bitfield >> 29) & 0x1) != 0;
noRelocation = ((bitfield >> 30) & 0x1) != 0;
hasLongReturn = ((bitfield >> 31) & 0x1) != 0;
symbolValue = reader.readNextUnsignedInt();
}
/**
* {@return whether or not the symbol is to be hidden from the loader for the purpose of
* resolving external (inter-SOM) references}
*/
public boolean isHidden() {
return hidden;
}
/**
* {@return whether or not the symbol is a secondary definition and has an additional name
* that is preceded by “_”}
*/
public boolean isSecondaryDef() {
return secondaryDef;
}
/**
* {@return the symbol type}
*
* @see SomConstants
*/
public int getSymbolType() {
return symbolType;
}
/**
* {@return the symbol scope}
*
* @see SomConstants
*/
public int getSymbolScope() {
return symbolScope;
}
/**
* {@return the check level}
*/
public int getCheckLevel() {
return checkLevel;
}
/**
* {@return whether or not the qualifier name must be used to fully qualify the symbol}
*/
public boolean mustQualify() {
return mustQualify;
}
/**
* {@return whether or not the code importing or exporting this symbol is to be locked in
* physical memory when the operating system is being booted}
*/
public boolean isInitiallyFrozen() {
return initiallyFrozen;
}
/**
* {@return whether or the the code that is importing or exporting this symbol is frozen in
* memory}
*/
public boolean isMemoryResident() {
return memoryResident;
}
/**
* {@return whether or not this symbol is an initialized common data block}
*/
public boolean isCommon() {
return isCommon;
}
/**
* {@return whether or not this symbol name may conflict with another symbol of the same name if
* both are of type data}
*/
public boolean isDupCommon() {
return dupCommon;
}
/**
* {@return the execution level that is required to call this entry point}
*/
public int getXleast() {
return xleast;
}
/**
* {@return the location of the first four words of the parameter list, and the location of the
* function return value to the linker and loader}
*/
public int getArgReloc() {
return argReloc;
}
/**
* {@return the symbol name}
*/
public String getName() {
return name;
}
/**
* {@return the symbol qualifier name}
*/
public String getQualifierName() {
return qualifierName;
}
/**
* {@return whether or not the called entry point will have a long return sequence}
*/
public boolean hasLongReturn() {
return hasLongReturn;
}
/**
* {@return whether or not the called entry point will not require any parameter relocation}
*/
public boolean hasNoRelocation() {
return noRelocation;
}
/**
* {@return whether or not this symbol identifies as the key symbol for a set of COMDAT
* subspaces}
*/
public boolean isComdat() {
return isComdat;
}
/**
* {@return the reserved value}
*/
public int getReserved() {
return reserved;
}
/**
* {@return the symbol info}
*/
public int getSymbolInfo() {
return symbolInfo;
}
/**
* {@return the symbol value}
*/
public long getSymbolValue() {
return symbolValue;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("symbol_dictionary_record", SIZE);
struct.setPackingEnabled(true);
try {
struct.addBitField(DWORD, 1, "hidden", null);
struct.addBitField(DWORD, 1, "secondary_def", null);
struct.addBitField(DWORD, 6, "symbol_type", null);
struct.addBitField(DWORD, 4, "symbol_scope", null);
struct.addBitField(DWORD, 3, "check_level", null);
struct.addBitField(DWORD, 1, "must_qualify", null);
struct.addBitField(DWORD, 1, "initially_frozen", null);
struct.addBitField(DWORD, 1, "memory_resident", null);
struct.addBitField(DWORD, 1, "is_common", null);
struct.addBitField(DWORD, 1, "dup_common", null);
struct.addBitField(DWORD, 2, "xleast", null);
struct.addBitField(DWORD, 10, "arg_reloc", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "name", null);
struct.add(DWORD, "qualifier_name", null);
try {
struct.addBitField(DWORD, 1, "has_long_return", null);
struct.addBitField(DWORD, 1, "no_relocation", null);
struct.addBitField(DWORD, 1, "is_comdat", null);
struct.addBitField(DWORD, 5, "reserved", null);
struct.addBitField(DWORD, 24, "symbol_info", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
struct.add(DWORD, "symbol_value", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
@Override
public String toString() {
return "name=%s, type=%d, scope=%d, value = 0x%x".formatted(name, symbolType, symbolScope,
symbolValue);
}
}

View File

@@ -0,0 +1,72 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a SOM {@code sys_clock} structure
*
* @see <a href="https://web.archive.org/web/20050502101134/http://devresource.hp.com/drc/STK/docs/archive/rad_11_0_32.pdf">The 32-bit PA-RISC Run-time Architecture Document</a>
*/
public class SomSysClock implements StructConverter {
/** The size in bytes of a {@link SomSysClock} */
public static final int SIZE = 0x8;
private long seconds;
private long nano;
/**
* Creates a new {@link SomSysClock}
*
* @param reader A {@link BinaryReader} positioned at the start of the value
* @throws IOException if there was an IO-related error
*/
public SomSysClock(BinaryReader reader) throws IOException {
seconds = reader.readNextUnsignedInt();
nano = reader.readNextUnsignedInt();
}
/**
* {@return the number of seconds that have elapsed since January 1, 1970 (at 0:00 GMT)}
*/
public long getSeconds() {
return seconds;
}
/**
* {@return the nano second of the second (which requires 30 bits to represent)}
*/
public long getNanoSeconds() {
return nano;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("sys_clock", SIZE);
struct.setPackingEnabled(true);
struct.add(DWORD, "seconds", null);
struct.add(DWORD, "nano", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,58 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents an unknown SOM auxiliary header
*/
public class SomUnknownAuxHeader extends SomAuxHeader {
private byte[] bytes;
/**
* Creates a new {@link SomUnknownAuxHeader}
*
* @param reader A {@link BinaryReader} positioned at the start of the auxiliary header
* @throws IOException if there was an IO-related error
*/
public SomUnknownAuxHeader(BinaryReader reader) throws IOException {
super(reader);
bytes = reader.readNextByteArray((int) auxId.getLength());
}
/**
* {@return the unknown bytes of this auxiliary header}
*/
public byte[] getBytes() {
return bytes;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("som_unknown_auxhdr", 0);
struct.setPackingEnabled(true);
struct.add(auxId.toDataType(), "som_auxhdr", null);
struct.add(new ArrayDataType(BYTE, (int) auxId.getLength(), 1), "bytes", null);
struct.setCategoryPath(new CategoryPath("/SOM"));
return struct;
}
}

View File

@@ -0,0 +1,313 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.opinion;
import static ghidra.app.util.bin.format.som.SomConstants.*;
import java.io.IOException;
import java.util.*;
import ghidra.app.util.MemoryBlockUtils;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.som.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
/**
* A {@link Loader} for System Object Model files
*/
public class SomLoader extends AbstractProgramWrapperLoader {
public final static String SOM_NAME = "System Object Model (SOM)";
@Override
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
List<LoadSpec> loadSpecs = new ArrayList<>();
if (provider.length() < SomHeader.SIZE) {
return loadSpecs;
}
try {
SomHeader header = new SomHeader(new BinaryReader(provider, false));
if (header.hasValidMagic() && header.hasValidVersionId()) {
List<QueryResult> results = QueryOpinionService.query(getName(),
Integer.toString(header.getSystemId()), null);
for (QueryResult result : results) {
loadSpecs.add(new LoadSpec(this, 0, result));
}
if (loadSpecs.isEmpty()) {
loadSpecs.add(new LoadSpec(this, 0, true));
}
}
}
catch (IOException e) {
// that's ok, not a System Object Model
}
return loadSpecs;
}
@Override
protected void load(Program program, ImporterSettings settings)
throws IOException, CancelledException {
MessageLog log = settings.log();
TaskMonitor monitor = settings.monitor();
FileBytes fileBytes =
MemoryBlockUtils.createFileBytes(program, settings.provider(), monitor);
BinaryReader reader = new BinaryReader(settings.provider(), false);
try {
SomHeader header = new SomHeader(reader);
processMemoryBlocks(program, fileBytes, header, log, monitor);
SomDynamicLoaderHeader dlHeader = new SomDynamicLoaderHeader(program,
header.getTextAddress(program), header.getDataAddress(program));
processEntryPoint(program, header, log, monitor);
processSymbols(program, header, log, monitor);
processImports(program, dlHeader, log, monitor);
processExports(program, dlHeader, log, monitor);
processLibraries(program, dlHeader, log, monitor);
markupHeaders(program, fileBytes, header, dlHeader, log, monitor);
}
catch (Exception e) {
throw new IOException(e);
}
}
private void processMemoryBlocks(Program program, FileBytes fileBytes, SomHeader header,
MessageLog log, TaskMonitor monitor) throws Exception {
monitor.setMessage("Processing memory blocks...");
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
List<SomSpace> spaces = header.getSpaces();
List<SomSubspace> subspaces = header.getSubspaces();
for (SomSubspace subspace : subspaces) {
SomSpace space = spaces.get(subspace.getSpaceIndex());
long initSize = subspace.getInitializationLength();
long size = subspace.getSubspaceLength();
if (size == 0) {
continue;
}
Address addr = subspace.isLoadable() ? addrSpace.getAddress(subspace.getSubspaceStart())
: AddressSpace.OTHER_SPACE.getAddress(subspace.getSubspaceStart());
if (initSize > 0) {
MemoryBlockUtils.createInitializedBlock(program, !subspace.isLoadable(),
subspace.getName(), addr, fileBytes, subspace.getFileLocInitValue(), initSize,
"", space.getName(), subspace.isRead(), subspace.isWrite(),
subspace.isExecute(), log);
addr = addr.add(initSize);
}
if (size > initSize) {
MemoryBlockUtils.createUninitializedBlock(program, !subspace.isLoadable(),
subspace.getName(), addr, size - initSize, "", space.getName(),
subspace.isRead(), subspace.isWrite(), subspace.isExecute(), log);
}
}
}
private void processEntryPoint(Program program, SomHeader header, MessageLog log,
TaskMonitor monitor) throws Exception {
monitor.setMessage("Processing entry point...");
SymbolTable symbolTable = program.getSymbolTable();
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
SomSpace space = header.getSpaces().get((int) header.getEntrySpace());
SomSubspace subspace =
header.getSubspaces().get((int) (space.getSubspaceIndex() + header.getEntrySubspace()));
Address subspaceAddr = addrSpace.getAddress(subspace.getSubspaceStart());
long entryOffset = 0;
SomExecAuxHeader execHeader = header.getFirstAuxHeader(SomExecAuxHeader.class);
if (execHeader != null) {
long execEntry = execHeader.getExecEntry();
if (execEntry != 0) {
entryOffset = execEntry;
}
}
if (entryOffset == 0) {
entryOffset = header.getEntryOffset();
}
if (entryOffset != 0) {
Address addr = subspaceAddr.add(entryOffset);
addr = addrSpace.getAddress(entryOffset);
AbstractProgramLoader.markAsFunction(program, "entry", addr);
symbolTable.addExternalEntryPoint(addr);
}
}
private void processSymbols(Program program, SomHeader header, MessageLog log,
TaskMonitor monitor) throws Exception {
SymbolTable symbolTable = program.getSymbolTable();
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
List<SomSymbol> somSymbols = header.getSymbols();
monitor.initialize(somSymbols.size(), "Processing symbols...");
for (SomSymbol somSymbol : somSymbols) {
monitor.increment();
if (somSymbol.getSymbolScope() == SYMBOL_SCOPE_UNSAT) {
// The symbol value is meaningless in this case, so don't create a symbol
continue;
}
Address addr = addrSpace.getAddress(somSymbol.getSymbolValue());
String name = SymbolUtilities.replaceInvalidChars(somSymbol.getName(), true);
// For code symbols, mask off bottom 2 permission bits
switch (somSymbol.getSymbolType()) {
case SYMBOL_ENTRY:
case SYMBOL_MILLICODE:
case SYMBOL_CODE:
addr = addr.getNewAddress(addr.getOffset() & 0xfffffffc);
}
// Create label on supported symbols
switch (somSymbol.getSymbolType()) {
case SYMBOL_ENTRY:
case SYMBOL_MILLICODE:
case SYMBOL_CODE:
case SYMBOL_DATA:
case SYMBOL_STUB:
symbolTable.createLabel(addr, name, SourceType.IMPORTED);
}
// Create functions on relevant symbols
switch (somSymbol.getSymbolType()) {
case SYMBOL_ENTRY:
case SYMBOL_MILLICODE:
AbstractProgramLoader.markAsFunction(program, name, addr);
}
}
}
private void processImports(Program program, SomDynamicLoaderHeader dlHeader, MessageLog log,
TaskMonitor monitor) throws Exception {
int importCounter = 0;
List<SomImportEntry> imports = dlHeader.getImports();
List<SomDltEntry> dlt = dlHeader.getDlt();
List<SomPltEntry> plt = dlHeader.getPlt();
SymbolTable symbolTable = program.getSymbolTable();
FunctionManager functionMgr = program.getFunctionManager();
ExternalManager extMgr = program.getExternalManager();
Address dataAddr = dlHeader.getDataAddress();
monitor.initialize(dlt.size(), "Processing DLT imports...");
for (int i = 0; i < dlt.size(); i++, importCounter++) {
monitor.increment();
SomImportEntry importEntry = imports.get(importCounter);
String importName = importEntry.getName();
if (importName != null) {
SomDltEntry dltEntry = dlt.get(i);
Address target = dataAddr.getNewAddress(dltEntry.getValue());
symbolTable.createLabel(target, importName, SourceType.IMPORTED);
extMgr.addExtLocation(Library.UNKNOWN, importName, null, SourceType.IMPORTED);
}
}
monitor.initialize(plt.size(), "Processing PLT imports...");
for (int i = 0; i < plt.size(); i++, importCounter++) {
monitor.increment();
SomImportEntry importEntry = imports.get(importCounter);
SomPltEntry pltEntry = plt.get(i);
Address target = dataAddr.getNewAddress(pltEntry.getProcAddr());
String name = importEntry.getName();
Function stubFunc = functionMgr.getFunctionAt(target);
if (stubFunc == null) {
stubFunc = functionMgr.createFunction(name, target, new AddressSet(target),
SourceType.IMPORTED);
}
ExternalLocation loc =
extMgr.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
stubFunc.setThunkedFunction(loc.createFunction());
}
}
private void processExports(Program program, SomDynamicLoaderHeader dlHeader, MessageLog log,
TaskMonitor monitor) throws Exception {
SymbolTable symbolTable = program.getSymbolTable();
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
List<SomExportEntry> exports = dlHeader.getExports();
monitor.initialize(exports.size(), "Processing exports...");
for (SomExportEntry export : dlHeader.getExports()) {
String name = export.getName();
if (name == null) {
continue;
}
Address addr = addrSpace.getAddress(export.getValue());
SymbolIterator iter = symbolTable.getSymbols(name);
if (!iter.hasNext()) {
symbolTable.createLabel(addr, name, SourceType.IMPORTED);
symbolTable.addExternalEntryPoint(addr);
}
else {
for (Symbol symbol : iter) {
if (symbol.getAddress().getOffset() == export.getValue()) {
symbolTable.addExternalEntryPoint(addr);
}
}
}
}
}
private void processLibraries(Program program, SomDynamicLoaderHeader dlHeader, MessageLog log,
TaskMonitor monitor) throws Exception {
monitor.initialize(dlHeader.getShlibListCount(), "Processing libraries...");
for (SomShlibListEntry entry : dlHeader.getShlibs()) {
String name = SymbolUtilities.replaceInvalidChars(entry.getShlibName(), true);
try {
program.getExternalManager().addExternalLibraryName(name, SourceType.IMPORTED);
}
catch (DuplicateNameException e) {
// do not care
}
catch (Exception e) {
log.appendMsg("Unable to add external library name: " + e.getMessage());
}
}
}
private void markupHeaders(Program program, FileBytes fileBytes, SomHeader header,
SomDynamicLoaderHeader dlHeader, MessageLog log, TaskMonitor monitor) {
monitor.setMessage("Marking up headers...");
Address headerSpaceAddr = AddressSpace.OTHER_SPACE.getAddress(0);
try {
MemoryBlock headerBlock = MemoryBlockUtils.createInitializedBlock(program, true,
"FILE", headerSpaceAddr, fileBytes, 0, fileBytes.getSize(), "", "", false, false,
false, log);
header.markup(program, headerBlock.getStart(), monitor);
}
catch (Exception e) {
log.appendMsg("Failed to markup headers: " + e.getMessage());
}
try {
dlHeader.markup(program, monitor);
}
catch (Exception e) {
log.appendMsg("Failed to markup dynamic loader headers: " + e.getMessage());
}
}
@Override
public String getName() {
return SOM_NAME;
}
}

View File

@@ -1,5 +1,10 @@
<opinions>
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="default">
<constraint primary="15" secondary="528" processor="PA-RISC" endian="big" size="32" />
<constraint primary="15" secondary="528" processor="PA-RISC" endian="big" size="32" />
</constraint>
<constraint loader="System Object Model (SOM)" compilerSpecID="default">
<constraint primary="523" processor="PA-RISC" endian="big" size="32" />
<constraint primary="528" processor="PA-RISC" endian="big" size="32" />
<constraint primary="532" processor="PA-RISC" endian="big" size="32" />
</constraint>
</opinions>