kpdump.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. Copyright 2018 Harvey OS Team
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. 1. Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. 2. Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. 3. Neither the name of the copyright holder nor the names of its contributors
  11. may be used to endorse or promote products derived from this software
  12. without specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  14. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  20. OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  22. OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  23. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. package main
  26. import (
  27. "debug/elf"
  28. "encoding/binary"
  29. "flag"
  30. "fmt"
  31. "io"
  32. "math"
  33. "os"
  34. )
  35. const LRES = 3
  36. var kernel = flag.String("k", "9k", "kernel name")
  37. func main() {
  38. flag.Parse()
  39. n := flag.Args()[0]
  40. d, err := os.Open(n)
  41. if err != nil {
  42. fmt.Fprintf(os.Stderr, "%v\n", err)
  43. os.Exit(1)
  44. }
  45. f, err := elf.Open(*kernel)
  46. if err != nil {
  47. fmt.Fprintf(os.Stderr, "%v\n", err)
  48. os.Exit(1)
  49. }
  50. var codeend uint64
  51. var codestart uint64 = math.MaxUint64
  52. for _, v := range f.Progs {
  53. if v.Type != elf.PT_LOAD {
  54. continue
  55. }
  56. fmt.Fprintf(os.Stderr, "processing %v\n", v)
  57. // MUST alignt to 2M page boundary.
  58. // then MUST allocate a []byte that
  59. // is the right size. And MUST
  60. // see if by some off chance it
  61. // joins to a pre-existing segment.
  62. // It's easier than it seems. We produce ONE text
  63. // array and ONE data array. So it's a matter of creating
  64. // a virtual memory space with an assumed starting point of
  65. // 0x200000, and filling it. We just grow that as needed.
  66. curstart := v.Vaddr
  67. curend := v.Vaddr + v.Memsz
  68. // magic numbers, BAH!
  69. if curstart < uint64(0xffffffff00000000) {
  70. curstart += 0xfffffffff0000000
  71. curend += 0xfffffffff0000000
  72. }
  73. fmt.Fprintf(os.Stderr, "s %x e %x\n", curstart, curend)
  74. if v.Flags&elf.PF_X == elf.PF_X {
  75. if curstart < codestart {
  76. codestart = curstart
  77. }
  78. if curend > codeend {
  79. codeend = curend
  80. }
  81. fmt.Fprintf(os.Stderr, "code s %x e %x\n", codestart, codeend)
  82. }
  83. }
  84. fmt.Fprintf(os.Stderr, "code s %x e %x\n", codestart, codeend)
  85. s, err := f.Symbols()
  86. if err != nil {
  87. fmt.Fprintf(os.Stderr, "%v\n", err)
  88. os.Exit(1)
  89. }
  90. // maybe we should stop doing LRES ...
  91. symname := make([]string, codeend-codestart)
  92. for i := range symname {
  93. symname[i] = fmt.Sprintf("[0x%x]", codestart+uint64(i))
  94. }
  95. for _, v := range s {
  96. vstart := v.Value
  97. vend := v.Value + v.Size
  98. if v.Value > codeend {
  99. continue
  100. }
  101. if v.Value+v.Size < codestart {
  102. continue
  103. }
  104. if vstart < codestart {
  105. v.Value = codestart
  106. }
  107. if vend > codeend {
  108. vend = codeend
  109. }
  110. for i := vstart; i < vend; i++ {
  111. symname[i-codestart] = v.Name
  112. }
  113. }
  114. symname[0] = "Total ms"
  115. symname[1<<LRES] = "Unknown"
  116. // now dump the info ...
  117. count := uint32(0)
  118. pc := codestart
  119. for {
  120. if err := binary.Read(d, binary.BigEndian, &count); err != nil {
  121. if err != io.EOF {
  122. fmt.Fprintf(os.Stderr, "%v\n", err)
  123. }
  124. break
  125. }
  126. if count > 0 {
  127. fmt.Printf("%s %d\n", symname[pc-codestart], count)
  128. }
  129. pc += (1 << LRES)
  130. }
  131. }