title: How to understand System.map output from linux kernel build (how I calculate physical address?)
body: <p>I have built a linux kernel image (arm64) and I can do disassembly using this command (goes out to stdout).</p>
  <pre><code>aarch64-none-elf-objdump -b binary -D -m aarch64 Image
  </code></pre>
  <p>The output looks like this.</p>
  <pre><code>arch/arm64/boot/Image:     file format binary
  
  
  Disassembly of section .data:
  
  0000000000000000 &lt;.data&gt;:
         0:   140fc000    b   0x3f0000                          &lt;=== see this branch to 3f0000
         4:   00000000    udf #0
         8:   00080000    .inst   0x00080000 ; undefined
         c:   00000000    udf #0
        10:   004bb000    .inst   0x004bb000 ; undefined
        14:   00000000    udf #0
  (skip) 
  
    3dbe48:   756e694c    .inst   0x756e694c ; undefined
    3dbe4c:   00000078    udf #120
      ...
    3f0000:   d280067b    mov x27, #0x3333                    // #51  \
    3f0004:   5800157c    ldr x28, 0x3f02b0                            |
    3f0008:   9100239c    add x28, x28, #0x8                           | added for debug
    3f000c:   f800879b    str x27, [x28], #8                           |
    3f0010:   5800151a    ldr x26, 0x3f02b0                            |
    3f0014:   f900035c    str x28, [x26]                               /
    3f0018:   94000008    bl  0x3f0038
    3f001c:   97fc47fb    bl  0x302008
  </code></pre>
  <p>The FPGA board I'm working on has only 8 MB on-chip ram (0x80000000 ~ 0x80800000) in place of DDR range(0x80000000 ~ ) for now and I loaded the kernel image to 0x80080000 and jumped to 0x80080000. (I'm using u-boot-spl to make this jump).  I can't use debugger for the board yet and I wanted to check if the linux kernel code really runs so added a simple debug code which writes 0x3333 at some memory location.  (The 6 lines at 0x3f0000 using x27 and x28 is the code.) Original linux code doesn't have it and would do <code>bl preserve_boot_args</code>. (here <code>bl 0x3f0038</code>).<br />
  This is the debug code I added in arch/arm64/kernel/start.S. (6 linex using x27, x28)</p>
  <pre><code>ENTRY(stext)
  
      mov x27, #0x3333            \
      ldr x28, =myptr              |
      add x28, x28, #8             |
      str x27, [x28], #8           |  added for debug
      ldr x26, =myptr              |
      str x28, [x26]               /
  
      bl  preserve_boot_args
      bl  el2_setup           // Drop to EL1, w0=cpu_boot_mode
  
  
  .section &quot;.__mydebug&quot;, &quot;aw&quot;
  myptr:  .double 0x807e0000
  </code></pre>
  <p>So if the next value of <code>myptr</code> is 0x3333, the code should have worked. I modified the linux linker script as below (added a section .mydebug) and made the value <code>myptr</code> be placed there.</p>
  <pre><code>   PECOFF_EDATA_PADDING
      __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
      _edata = .;
  
      .mydebug : {                  \
          . = ALIGN(8);              |  ==&gt; added section
          KEEP(*(.__mydebug));       |
      }                             /
  
      BSS_SECTION(0, 0, 0)
  
      . = ALIGN(PAGE_SIZE);
      init_pg_dir = .;
  </code></pre>
  <p>And the System.map file looks like this.</p>
  <pre><code>0000000000000000 A __rela_size
  0000000000000000 A _kernel_flags_le_hi32
  0000000000000000 A _kernel_offset_le_hi32
  0000000000000000 A _kernel_size_le_hi32
  000000000000000a A _kernel_flags_le_lo32
  0000000000000200 A PECOFF_FILE_ALIGNMENT
  000000000006b808 A __pecoff_data_rawsize
  0000000000080000 A _kernel_offset_le_lo32
  0000000000095000 A __pecoff_data_size
  00000000004bb000 A _kernel_size_le_lo32
  00000000004be948 A __rela_offset
  ffffffc010080000 t _head
  ffffffc010080000 T _text
  ffffffc010080800 T __exception_text_start
  ffffffc010080800 T _stext
  ffffffc010080800 T do_undefinstr
  ffffffc0100809d0 T do_sysinstr
  ffffffc010080a40 T do_mem_abort
  ffffffc010080ae0 T do_el0_irq_bp_hardening
  ffffffc010080b60 T do_el0_ia_bp_hardening
  (skip)
  ffffffc010511800 D secondary_holding_pen_release
  ffffffc010511808 D __mmuoff_data_end
  ffffffc010511808 D _edata
  ffffffc010511808 D myptr              &lt;==== see this
  ffffffc010511810 B __bss_start
  ffffffc010512000 b bm_pmd
  ffffffc010513000 b bm_pte
  ffffffc010514000 B empty_zero_page
  ffffffc010515000 B reset_devices
  ffffffc010515008 b execute_command
  ffffffc010515010 b ramdisk_execute_command
  </code></pre>
  <p>I wanted to see the value of <code>myptr</code> and the next value.(all 64 bit). But the System.map shows all virtual addresses. How can I know the physical address of <code>myptr</code>?  In previous baremetal programas, I could see the memory using the map file (it showed the physical address, virtual=physical), but in this case the System.map shows virtual addresses which I can't localize.. I tried looking at 0x80080000 + 0x3f0004 + 0x3f02b0  or 0x80080000 + 0x3f02b0 but couldn't find it.  How can I find the location of <code>myptr</code>??</p>
  <p><strong>ADD (Jan 5, 2022) :</strong><br />
  I found .mysection is followed by _bss which will be initialized by 0, so I added some space before _bss_start. And I thought the instruction <code>3f0004:   5800157c    ldr x28, 0x3f02b0</code> is ldr (literal) instruction in armv8 arch ref manual C6.2.133 (by first two bits). So the value 0x3f02b0 is PC relative. The PC value at the instant is 0x3f0008 (already incremented by 4) so 0x3f0008 + 0x3f02b0 = 0x7e02b8. Since the kernel images starts at 0x80080000, this location is 0x80080000 + 0x7e02b8 = 0x808602b8 which goes beyond the 8MB range(0x80000000 ~ 0x80800000). If I placed the kernel at 0x80000000, this value would become 0x807e02b8 (in the RAM range).
  But still there were strange values in the address next to the address I think is myptr location.  And I found the PAGE_OFFSET is 0xffffff00_00000000 by printing it during compile in the file arch/arm64/include/asm/memory.h.(not 0xffffffc0_00000000 as shown in System.map). I tried looking at <code>(address of myptr according to System.map) - PAGE_OFFSET + (kernel load address = 0x80000000)</code> but couldn't find 0x3333 written in address next to myptr. I tried assuming PAGE_OFFSET 0xffffffc010000000 (then myptr becomes 0x80511808) and 0xffffff0000000000 (then myptr becomes 0xc090511808 which is too big).</p>