...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/time/asset_linux_arm64.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/time

     1  // Copyright 2022 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package time
    17  
    18  import (
    19  	"debug/elf"
    20  	"encoding/binary"
    21  )
    22  
    23  func AssetLD(rela elf.Rela64, imageOffset map[string]int, imageContent *[]byte, sym elf.Symbol, byteorder binary.ByteOrder) {
    24  	imageOffset[sym.Name] = len(*imageContent)
    25  
    26  	targetOffset := uint32(len(*imageContent)) - uint32(rela.Off) + uint32(rela.Addend)
    27  
    28  	// The relocation of a aarch64 image is like:
    29  	// Offset          Info           Type           Sym. Value    Sym. Name + Addend
    30  	// 000000000010  000b00000135 R_AARCH64_GOT_LD_ 0000000000000000 CLOCK_IDS_MASK + 0
    31  	// 00000000002c  000c00000135 R_AARCH64_GOT_LD_ 0000000000000000 TV_NSEC_DELTA + 0
    32  	// 000000000034  000d00000135 R_AARCH64_GOT_LD_ 0000000000000000 TV_SEC_DELTA + 0
    33  
    34  	// we assume the type is always R_AARCH64_GOT_LD_PREL19, with `-mcmodel=tiny`
    35  
    36  	// In this situation, we need to push two uint64 to the end:
    37  	// One for the location of variable, and one for the variable
    38  
    39  	// For example, if the entry starts at 0x00, and we have two variables whose value are
    40  	// 0xFF and 0xFE. We will have 32 bytes after the content:
    41  	// | 0x00 | 0x08 | 0x10 | 0x18 |
    42  	// | 0x08 | 0xFF | 0x18 | 0xFE |
    43  
    44  	// See the manual of LDR (literal) and LDR (register) to understand the
    45  	// relocation based on the following assemblies:
    46  	//
    47  	// ldr x1, #OFFSET_OF_ADDR ; in this step, the address of variable is loaded
    48  	//                           into the x1 register
    49  	// ldr x1, [x1]            ; in this step, the variable itself is loaded into
    50  	//                           the register
    51  
    52  	targetOffset >>= 2
    53  	instr := byteorder.Uint32((*imageContent)[rela.Off : rela.Off+4])
    54  
    55  	// See the document of instruction
    56  	// [ldr](https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--literal---Load-Register--literal--?lang=en)
    57  	// the offset is saved in `imm19`, and the max length is 19 (bit)
    58  	//
    59  	// 1. cut `instr` at [0:4] and [23:31]
    60  	// 2. cut the little 19 bit of `targetOffset`, and shift it to [5:23]
    61  	// 3. concat them
    62  	instr = uint32(int(instr) & ^((1<<19-1)<<5)) | ((targetOffset & (1<<19 - 1)) << 5)
    63  	byteorder.PutUint32((*imageContent)[rela.Off:rela.Off+4], instr)
    64  
    65  	// TODO: support other length besides uint64 (which is 8 bytes)
    66  	*imageContent = append(*imageContent, make([]byte, varLength)...)
    67  }
    68