mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-09 14:08:03 -05:00
GP-5942: Loader for "System Object Model" binaries
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user