mirror of
https://github.com/blacktop/ipsw.git
synced 2026-06-07 12:27:36 +00:00
216 lines
6.0 KiB
Go
216 lines
6.0 KiB
Go
package kernel
|
|
|
|
import (
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/blacktop/ipsw/api/types"
|
|
mcmd "github.com/blacktop/ipsw/internal/commands/macho"
|
|
"github.com/blacktop/ipsw/pkg/kernelcache"
|
|
"github.com/blacktop/ipsw/pkg/kernelcache/cpp"
|
|
"github.com/blacktop/ipsw/pkg/signature"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type kernelPathParams struct {
|
|
Path string `form:"path" json:"path" binding:"required"`
|
|
Arch string `form:"arch" json:"arch"`
|
|
}
|
|
|
|
type kernelCPPParams struct {
|
|
Path string `form:"path" json:"path" binding:"required"`
|
|
Arch string `form:"arch" json:"arch"`
|
|
Entry []string `form:"entry" json:"entry"`
|
|
Class string `form:"class" json:"class"`
|
|
Limit int `form:"limit" json:"limit"`
|
|
}
|
|
|
|
type kernelSymbolicateParams struct {
|
|
Path string `form:"path" json:"path" binding:"required"`
|
|
Arch string `form:"arch" json:"arch"`
|
|
Signatures string `form:"signatures" json:"signatures"`
|
|
}
|
|
|
|
// swagger:response kernelKextsResponse
|
|
type kernelKextsResponse struct {
|
|
Path string `json:"path"`
|
|
Kexts []kernelcache.CFBundle `json:"kexts"`
|
|
}
|
|
|
|
// swagger:response kernelCPPResponse
|
|
type kernelCPPResponse struct {
|
|
Path string `json:"path"`
|
|
Arch string `json:"arch,omitempty"`
|
|
Count int `json:"count"`
|
|
Classes []cpp.Class `json:"classes"`
|
|
}
|
|
|
|
// swagger:response kernelSymbolicateResponse
|
|
type kernelSymbolicateResponse struct {
|
|
Path string `json:"path"`
|
|
Arch string `json:"arch,omitempty"`
|
|
Symbols signature.SymbolMap `json:"symbols"`
|
|
}
|
|
|
|
func openKernel(path, arch string) (*mcmd.MachO, string, error) {
|
|
kernelPath := filepath.Clean(path)
|
|
m, err := mcmd.OpenMachONonInteractive(kernelPath, arch, false)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
return m, kernelPath, nil
|
|
}
|
|
|
|
func listKexts(c *gin.Context) {
|
|
var params kernelPathParams
|
|
if err := c.BindQuery(¶ms); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
m, kernelPath, err := openKernel(params.Path, params.Arch)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
defer m.Close()
|
|
|
|
bundles, err := kernelcache.GetKexts(m.File)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, kernelKextsResponse{Path: kernelPath, Kexts: bundles})
|
|
}
|
|
|
|
// swagger:response kernelSyscallsResponse
|
|
type kernelSyscallsResponse struct {
|
|
Path string `json:"path"`
|
|
Syscalls []kernelcache.Sysent `json:"syscalls"`
|
|
}
|
|
|
|
func getSyscalls(c *gin.Context) {
|
|
var params kernelPathParams
|
|
if err := c.BindQuery(¶ms); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
m, kernelPath, err := openKernel(params.Path, params.Arch)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
defer m.Close()
|
|
|
|
_, syscalls, err := kernelcache.GetSyscallTable(m.File)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, kernelSyscallsResponse{Path: kernelPath, Syscalls: syscalls})
|
|
}
|
|
|
|
// swagger:response kernelVersionResponse
|
|
type kernelVersionResponse struct {
|
|
Path string `json:"path"`
|
|
Version *kernelcache.Version `json:"version"`
|
|
}
|
|
|
|
func getVersion(c *gin.Context) {
|
|
var params kernelPathParams
|
|
if err := c.BindQuery(¶ms); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
m, kernelPath, err := openKernel(params.Path, params.Arch)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
defer m.Close()
|
|
|
|
v, err := kernelcache.GetVersion(m.File)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"path": kernelPath, "version": v})
|
|
}
|
|
|
|
func kernelCPP(c *gin.Context) {
|
|
var params kernelCPPParams
|
|
if err := c.BindQuery(¶ms); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
m, kernelPath, err := openKernel(params.Path, params.Arch)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
defer m.Close()
|
|
|
|
classes, err := cpp.NewScanner(m.File, cpp.Config{
|
|
Entries: params.Entry,
|
|
ClassName: strings.TrimSpace(params.Class),
|
|
}).Scan()
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
if params.Limit > 0 && params.Limit < len(classes) {
|
|
classes = classes[:params.Limit]
|
|
}
|
|
|
|
c.IndentedJSON(http.StatusOK, kernelCPPResponse{
|
|
Path: kernelPath,
|
|
Arch: params.Arch,
|
|
Count: len(classes),
|
|
Classes: classes,
|
|
})
|
|
}
|
|
|
|
func symbolicateKernel(c *gin.Context) {
|
|
var params kernelSymbolicateParams
|
|
if err := c.BindQuery(¶ms); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
m, kernelPath, err := openKernel(params.Path, params.Arch)
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
defer m.Close()
|
|
|
|
var sigs []signature.Symbolicator
|
|
if params.Signatures != "" {
|
|
sigs, err = signature.Parse(filepath.Clean(params.Signatures))
|
|
if err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
}
|
|
|
|
smap := signature.NewSymbolMap()
|
|
if err := smap.SymbolicateMachO(m.File, filepath.Base(kernelPath), sigs, true); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()})
|
|
return
|
|
}
|
|
|
|
c.IndentedJSON(http.StatusOK, kernelSymbolicateResponse{
|
|
Path: kernelPath,
|
|
Arch: params.Arch,
|
|
Symbols: smap,
|
|
})
|
|
}
|