#!/usr/bin/env vpython3 # # Copyright 2024 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. '''
Embed the address and size of elf sections into the pre-defined symbols.
The embedded values are used for performance optimization by mlock(2)ing the
sections on ChromeOS. See chromeos/ash/components/memory/memory.cc for details. '''
import argparse import os import subprocess import sys import shutil
def parse_endianess(objdump_result): for line in objdump_result.splitlines():
line = line.strip() if line.startswith('Data:'): if'1'in line: return'big' if'2'in line: return'little' raise ValueError('No endian found')
def assert_elf_type(objdump_result): for line in objdump_result.splitlines():
line = line.strip() if line.startswith('Class:'): if'ELF64'in line or'ELF32'in line: return raise ValueError('Class is not ELF64 nor ELF32: ' + line) raise ValueError('No class found')
def parse_section_info(objdump_result, section_name): for line in objdump_result.splitlines():
row = line.strip().split() if len(row) < 2: continue if row[1] == section_name: # 3: Address, 4: Offset, 5: Size return (int(row[3], base=16), int(row[4], base=16), int(row[5], base=16)) return (0, 0, 0)
command = [llvm_readelf, '--symbols', binary_input] with subprocess.Popen(command, stdout=subprocess.PIPE, text=True) as process:
variable_names = [
var for maps in TARGET_SECTIONS.values() for var in maps.values()
]
result = {} while len(result) < len(variable_names):
line = process.stdout.readline() ifnot line: break for var in variable_names: if var in line:
row = line.strip().split() if row[2] == '8':
size = 8 elif row[2] == '4':
size = 4 else: raise ValueError('variable size is not 8 or 4: ' + line)
addr = int(row[1], base=16)
rodata_section_end_addr = rodata_section_addr + rodata_section_size if addr < rodata_section_addr or addr >= rodata_section_end_addr: raise ValueError(var + ' is not in .rodata section')
offset = addr - rodata_section_addr + rodata_section_offset
result[var] = (offset, size)
return result
def overwrite_variable(file, symbol_map, endianess, section_name, var_type,
value):
(var_offset, var_size) = symbol_map[TARGET_SECTIONS[section_name][var_type]]
file.seek(var_offset) if file.write(
value.to_bytes(length=var_size, byteorder=endianess,
signed=False)) != var_size: raise ValueError('failed to write value to file')
def main():
argparser = argparse.ArgumentParser(
description='embed sections informataion into binary.')