Class GoRttiMapper

java.lang.Object
ghidra.app.util.bin.format.golang.structmapping.DataTypeMapper
ghidra.app.util.bin.format.golang.rtti.GoRttiMapper
All Implemented Interfaces:
AutoCloseable

public class GoRttiMapper extends DataTypeMapper
DataTypeMapper for golang binaries.

When bootstrapping golang binaries, the following steps are used:

  • Find the GoBuildInfo struct. This struct is the easiest to locate, even when the binary is stripped. This gives us the go pointerSize (probably same as ghidra pointer size) and the goVersion. This struct does not rely on StructureMapping, allowing its use before a DataTypeMapper is created.
  • Create DataTypeMapper
  • Find the runtime.firstmoduledata structure.
    • If there are symbols, just use the symbol or named memory block.
    • If stripped:
      • Find the pclntab. This has a magic signature, a pointerSize, and references to a couple of tables that are also referenced in the moduledata structure.
      • Search memory for a pointer to the pclntab struct. This should be the first field of the moduledata structure. The values that are duplicated between the two structures can be compared to ensure validity.
      • Different binary formats (Elf vs PE) will determine which memory blocks to search.
  • Constructor Details

    • GoRttiMapper

      public GoRttiMapper(Program program, int ptrSize, Endian endian, GoVer goVersion, ResourceFile archiveGDT) throws IOException, IllegalArgumentException
      Creates a GoRttiMapper using the specified bootstrap information.
      Parameters:
      program - Program containing the go binary
      ptrSize - size of pointers
      endian - Endian
      goVersion - version of go
      archiveGDT - path to the matching golang bootstrap gdt data type file, or null if not present and types recovered via DWARF should be used instead
      Throws:
      IOException - if error linking a structure mapped structure to its matching ghidra structure, which is a programming error or a corrupted bootstrap gdt
      IllegalArgumentException - if there is no matching bootstrap gdt for this specific type of golang binary
  • Method Details

    • getMapperFor

      public static GoRttiMapper getMapperFor(Program program, MessageLog log) throws IOException
      Returns a new GoRttiMapper for the specified program, or null if the binary is not a supported golang binary.
      Parameters:
      program - Program
      log - MessageLog
      Returns:
      new GoRttiMapper, or null if not a golang binary
      Throws:
      IOException - if bootstrap gdt is corrupted or some other struct mapping logic error
    • getGDTFilename

      public static String getGDTFilename(GoVer goVer, int pointerSizeInBytes, String osName)
      Returns the name of the golang bootstrap gdt data type archive, using the specified version, pointer size and OS name.
      Parameters:
      goVer - GoVer
      pointerSizeInBytes - pointer size for this binary, or -1 to use wildcard "any"
      osName - name of the operating system, or "any"
      Returns:
      String, "golang_1.18_64bit_any.gdt"
    • getGolangOSString

      public static String getGolangOSString(Program program)
      Returns a golang OS string based on the Ghidra program.
      Parameters:
      program - Program
      Returns:
      String golang OS string such as "linux", "win"
    • findGolangBootstrapGDT

      public static ResourceFile findGolangBootstrapGDT(GoVer goVer, int ptrSize, String osName)
      Searches for a golang bootstrap gdt file that matches the specified Go version/size/OS.

      First looks for a gdt with an exact match, then for a gdt with version/size match and "any" OS, and finally, a gdt that matches the version and "any" size and "any" OS.

      Parameters:
      goVer - version of Go
      ptrSize - size of pointers
      osName - name of OS
      Returns:
      ResourceFile of matching bootstrap gdt, or null if nothing matches
    • getGolangVersion

      public GoVer getGolangVersion()
      Returns the golang version
      Returns:
      GoVer
    • getRegInfo

      public GoRegisterInfo getRegInfo()
    • init

      public void init(TaskMonitor monitor) throws IOException
      Throws:
      IOException
    • getFirstModule

      public GoModuledata getFirstModule()
      Returns the first module data instance
      Returns:
      GoModuledata
    • addModule

      public void addModule(GoModuledata module)
      Adds a module data instance to the context
      Parameters:
      module - GoModuledata to add
    • getStorageAllocator

      public GoParamStorageAllocator getStorageAllocator()
    • isGolangAbi0Func

      public boolean isGolangAbi0Func(Function func)
    • getAbi0CallingConvention

      public PrototypeModel getAbi0CallingConvention()
    • getAbiInternalCallingConvention

      public PrototypeModel getAbiInternalCallingConvention()
    • getDuffzeroCallingConvention

      public PrototypeModel getDuffzeroCallingConvention()
    • getDuffcopyCallingConvention

      public PrototypeModel getDuffcopyCallingConvention()
    • findContainingModule

      public GoModuledata findContainingModule(long offset)
      Finds the GoModuledata that contains the specified offset.

      Useful for finding the GoModuledata to resolve a relative offset of the text, types or other area.

      Parameters:
      offset - absolute offset of a structure that a GoModuledata contains
      Returns:
      GoModuledata instance that contains the structure, or null if not found
    • findContainingModuleByFuncData

      public GoModuledata findContainingModuleByFuncData(long offset)
      Finds the GoModuledata that contains the specified func data offset.
      Parameters:
      offset - absolute offset of a func data structure
      Returns:
      GoModuledata instance that contains the specified func data, or null if not found
    • getDefaultVariableLengthStructCategoryPath

      public CategoryPath getDefaultVariableLengthStructCategoryPath()
      Description copied from class: DataTypeMapper
      CategoryPath location (in the program) where new data types will be created to represent variable length structures.
      Overrides:
      getDefaultVariableLengthStructCategoryPath in class DataTypeMapper
      Returns:
      CategoryPath, default is ROOT
    • getUintptrDT

      public DataType getUintptrDT()
      Returns the data type that represents a golang uintptr
      Returns:
      golang uinptr data type
    • getInt32DT

      public DataType getInt32DT()
      Returns the data type that represents a golang int32
      Returns:
      golang int32 data type
    • getUint32DT

      public DataType getUint32DT()
      Returns the data type that represents a golang uint32
      Returns:
      golang uint32 data type
    • getGenericSliceDT

      public Structure getGenericSliceDT()
      Returns the data type that represents a generic golang slice.
      Returns:
      golang generic slice data type
    • getMapGoType

      public GoType getMapGoType()
      Returns the ghidra data type that represents a golang built-in map type.
      Returns:
      golang map data type
    • getChanGoType

      public GoType getChanGoType()
      Returns the ghidra data type that represents the built-in golang channel type.
      Returns:
      golang channel type
    • createProgramReader

      protected BinaryReader createProgramReader()
      Description copied from class: DataTypeMapper
      Creates a new BinaryReader that reads bytes from the current program's memory image.

      Address offsets and index offsets in the BinaryReader should be synonymous.

      Overrides:
      createProgramReader in class DataTypeMapper
      Returns:
      new BinaryReader
    • getPtrSize

      public int getPtrSize()
      Returns the size of pointers in this binary.
      Returns:
      pointer size (ex. 4, or 8)
    • getGoType

      public GoType getGoType(long offset) throws IOException
      Returns a specialized GoType for the type that is located at the specified location.
      Parameters:
      offset - absolute position of a go type
      Returns:
      specialized GoType (example, GoStructType, GoArrayType, etc)
      Throws:
      IOException - if error reading
    • getGoType

      public GoType getGoType(Address addr) throws IOException
      Returns a specialized GoType for the type that is located at the specified location.
      Parameters:
      addr - location of a go type
      Returns:
      specialized GoType (example, GoStructType, GoArrayType, etc)
      Throws:
      IOException - if error reading
    • getLastGoType

      public GoType getLastGoType()
    • findGoType

      public GoType findGoType(String typeName)
      Finds a go type by its go-type name, from the list of discovered go types.
      Parameters:
      typeName - name string
      Returns:
      GoType, or null if not found
    • getGhidraDataType

      public <T extends DataType> T getGhidraDataType(String goTypeName, Class<T> clazz)
      Returns the Ghidra DataType that is equivalent to the named golang type.
      Type Parameters:
      T - expected DataType
      Parameters:
      goTypeName - golang type name
      clazz - class of expected data type
      Returns:
      DataType representing the named golang type, or null if not found
    • exportTypesToGDT

      public void exportTypesToGDT(File gdtFile, TaskMonitor monitor) throws IOException
      Export the currently registered struct mapping types to a gdt file, producing a bootstrap GDT archive.

      The struct data types will either be from the current program's DWARF data, or from an earlier golang.gdt (if this binary doesn't have DWARF)

      Parameters:
      gdtFile - destination File to write the bootstrap types to
      monitor - TaskMonitor
      Throws:
      IOException - if error
    • getRecoveredTypesCp

      public CategoryPath getRecoveredTypesCp()
      Returns category path that should be used to place recovered golang types.
      Returns:
      CategoryPath to use when creating recovered golang types
    • getRecoveredType

      public DataType getRecoveredType(GoType typ) throws IOException
      Returns a Ghidra data type that represents the golang type, using a cache of already recovered types to eliminate extra work and self recursion.
      Parameters:
      typ - the GoType to convert
      Returns:
      Ghidra DataType
      Throws:
      IOException - if error converting type
    • cacheRecoveredDataType

      public void cacheRecoveredDataType(GoType typ, DataType dt) throws IOException
      Inserts a mapping between a golang type and a ghidra data type.

      Useful to prepopulate the data type mapping before recursing into contained/referenced types that might be self-referencing.

      Parameters:
      typ - golang type
      dt - Ghidra type
      Throws:
      IOException - if golang type struct is not a valid struct mapped instance
    • getCachedRecoveredDataType

      public DataType getCachedRecoveredDataType(GoType typ) throws IOException
      Returns a Ghidra data type that represents the golang type, using a cache of already recovered types to eliminate extra work and self recursion.
      Parameters:
      typ - the GoType to convert
      Returns:
      Ghidra DataType
      Throws:
      IOException - if golang type struct is not a valid struct mapped instance
    • recoverDataTypes

      public void recoverDataTypes(TaskMonitor monitor) throws IOException, CancelledException
      Converts all discovered golang rtti type records to Ghidra data types, placing them in the program's DTM in /golang-recovered
      Parameters:
      monitor - TaskMonitor
      Throws:
      IOException - error converting a golang type to a Ghidra type
      CancelledException - if the user cancelled the import
    • discoverGoTypes

      public void discoverGoTypes(TaskMonitor monitor) throws IOException, CancelledException
      Iterates over all golang rtti types listed in the GoModuledata struct, and recurses into each type to discover any types they reference.

      The found types are accumulated in goTypes.

      Parameters:
      monitor - TaskMonitor
      Throws:
      IOException - if error
      CancelledException - if cancelled
    • resolveTypeOff

      public GoType resolveTypeOff(long ptrInModule, long off) throws IOException
      Returns the GoType corresponding to an offset that is relative to the controlling GoModuledata's typesOffset.
      Parameters:
      ptrInModule - the address of the structure that contains the offset that needs to be calculated. The containing-structure's address is important because it indicates which GoModuledata is the 'parent'
      off - offset
      Returns:
      GoType, or null if offset is special value 0 or -1
      Throws:
      IOException - if error
    • resolveTextOff

      public Address resolveTextOff(long ptrInModule, long off)
      Returns the Address to an offset that is relative to the controlling GoModuledata's text value.
      Parameters:
      ptrInModule - the address of the structure that contains the offset that needs to be calculated. The containing-structure's address is important because it indicates which GoModuledata is the 'parent'
      off - offset
      Returns:
      Address, or null if offset was special value -1
    • resolveNameOff

      public GoName resolveNameOff(long ptrInModule, long off) throws IOException
      Returns the GoName corresponding to an offset that is relative to the controlling GoModuledata's typesOffset.

      Parameters:
      ptrInModule - the address of the structure that contains the offset that needs to be calculated. The containing-structure's address is important because it indicates which GoModuledata is the 'parent'
      off - offset
      Returns:
      GoName, or null if offset was special value 0
      Throws:
      IOException - if error reading name or unable to find containing module
    • getGoName

      public GoName getGoName(long offset) throws IOException
      Returns the GoName instance at the specified offset.
      Parameters:
      offset - location to read
      Returns:
      GoName instance, or null if offset was special value 0
      Throws:
      IOException - if error reading
    • getFunctionData

      public GoFuncData getFunctionData(Address funcAddr) throws IOException
      Throws:
      IOException
    • getFunctionByName

      public GoFuncData getFunctionByName(String funcName)
    • getAllFunctions

      public List<GoFuncData> getAllFunctions() throws IOException
      Throws:
      IOException