...

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

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

     1  // Copyright 2021 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  	"bytes"
    20  	"debug/elf"
    21  	"embed"
    22  	"encoding/binary"
    23  
    24  	"github.com/go-logr/logr"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  //go:embed fakeclock/*.o
    29  var fakeclock embed.FS
    30  
    31  const textSection = ".text"
    32  const relocationSection = ".rela.text"
    33  
    34  // LoadFakeImageFromEmbedFs builds FakeImage from the embed filesystem. It parses the ELF file and extract the variables from the relocation section, reserves the space for them at the end of content, then calculates and saves offsets as "manually relocation"
    35  func LoadFakeImageFromEmbedFs(filename string, symbolName string, logger logr.Logger) (*FakeImage, error) {
    36  	path := "fakeclock/" + filename
    37  	object, err := fakeclock.ReadFile(path)
    38  	if err != nil {
    39  		return nil, errors.Wrapf(err, "read file from embedded fs %s", path)
    40  	}
    41  
    42  	elfFile, err := elf.NewFile(bytes.NewReader(object))
    43  	if err != nil {
    44  		return nil, errors.Wrapf(err, "parse elf file %s", path)
    45  	}
    46  
    47  	syms, err := elfFile.Symbols()
    48  	if err != nil {
    49  		return nil, errors.Wrapf(err, "get symbols %s", path)
    50  	}
    51  
    52  	var imageContent []byte
    53  	imageOffset := make(map[string]int)
    54  
    55  	for _, r := range elfFile.Sections {
    56  
    57  		if r.Type == elf.SHT_PROGBITS && r.Name == textSection {
    58  			imageContent, err = r.Data()
    59  			if err != nil {
    60  				return nil, errors.Wrapf(err, "read text section data %s", path)
    61  			}
    62  			break
    63  		}
    64  	}
    65  
    66  	for _, r := range elfFile.Sections {
    67  		if r.Type == elf.SHT_RELA && r.Name == relocationSection {
    68  			rela_section, err := r.Data()
    69  			if err != nil {
    70  				return nil, errors.Wrapf(err, "read rela section data %s", path)
    71  			}
    72  			rela_section_reader := bytes.NewReader(rela_section)
    73  
    74  			var rela elf.Rela64
    75  			for rela_section_reader.Len() > 0 {
    76  				err := binary.Read(rela_section_reader, elfFile.ByteOrder, &rela)
    77  				if err != nil {
    78  					return nil, errors.Wrapf(err, "read rela section rela64 entry %s", path)
    79  				}
    80  
    81  				symNo := rela.Info >> 32
    82  				if symNo == 0 || symNo > uint64(len(syms)) {
    83  					continue
    84  				}
    85  
    86  				sym := syms[symNo-1]
    87  				byteorder := elfFile.ByteOrder
    88  				if elfFile.Machine == elf.EM_X86_64 || elfFile.Machine == elf.EM_AARCH64 {
    89  					AssetLD(rela, imageOffset, &imageContent, sym, byteorder)
    90  				} else {
    91  					return nil, errors.Errorf("unsupported architecture")
    92  				}
    93  			}
    94  
    95  			break
    96  		}
    97  	}
    98  	return NewFakeImage(
    99  		symbolName,
   100  		imageContent,
   101  		imageOffset,
   102  		logger,
   103  	), nil
   104  }
   105