parameters: (objcopy, input_elf, output_elf, partition)
docstring: Extracts a partition from an ELF file.
  
    For partitions other than main partition, we need to rewrite
    the .note.gnu.build-id section so that the build-id remains
    unique.
  
    Note:
    - `objcopy` does not modify build-id when partitioning the
      combined ELF file by default.
    - The new build-id is calculated as hash of original build-id
      and partitioned ELF file name.
  
    Args:
      objcopy: Path to objcopy binary.
      input_elf: Path to input ELF file.
      output_elf: Path to output ELF file.
      partition: Partition to extract from combined ELF file. None when
        extracting main partition.
docstring_summary: Extracts a partition from an ELF file.
docstring_tokens: Extracts a partition from an ELF file .
function: def _ExtractPartition(objcopy, input_elf, output_elf, partition):
    """
    Extracts a partition from an ELF file.
  
    For partitions other than main partition, we need to rewrite
    the .note.gnu.build-id section so that the build-id remains
    unique.
  
    Note:
    - `objcopy` does not modify build-id when partitioning the
      combined ELF file by default.
    - The new build-id is calculated as hash of original build-id
      and partitioned ELF file name.
  
    Args:
      objcopy: Path to objcopy binary.
      input_elf: Path to input ELF file.
      output_elf: Path to output ELF file.
      partition: Partition to extract from combined ELF file. None when
        extracting main partition.
    """
    if not partition:  # main partition
      # We do not overwrite build-id on main partition to allow the expected
      # partition build ids to be synthesized given a libchrome.so binary,
      # if necessary.
      subprocess.check_call(
          [objcopy, '--extract-main-partition', input_elf, output_elf])
      return
  
    # partitioned libs
    build_id_section = '.note.gnu.build-id'
  
    with tempfile.TemporaryDirectory() as tempdir:
      temp_elf = os.path.join(tempdir, 'obj_without_id.so')
      old_build_id_file = os.path.join(tempdir, 'old_build_id')
      new_build_id_file = os.path.join(tempdir, 'new_build_id')
  
      # Dump out build-id section and remove original build-id section from
      # ELF file.
      subprocess.check_call([
          objcopy,
          '--extract-partition',
          partition,
          # Note: Not using '--update-section' here as it is not supported
          # by llvm-objcopy.
          '--remove-section',
          build_id_section,
          '--dump-section',
          '{}={}'.format(build_id_section, old_build_id_file),
          input_elf,
          temp_elf,
      ])
  
      with open(old_build_id_file, 'rb') as f:
        note_content = f.read()
  
      # .note section has following format according to <elf/external.h>
      #   typedef struct {
      #       unsigned char   namesz[4];  /* Size of entry's owner string */
      #       unsigned char   descsz[4];  /* Size of the note descriptor */
      #       unsigned char   type[4];    /* Interpretation of the descriptor */
      #       char        name[1];        /* Start of the name+desc data */
      #   } Elf_External_Note;
      # `build-id` rewrite is only required on Android platform,
      # where we have partitioned lib.
      # Android platform uses little-endian.
      # <: little-endian
      # 4x: Skip 4 bytes
      # L: unsigned long, 4 bytes
      descsz, = struct.Struct('<4xL').unpack_from(note_content)
      prefix = note_content[:-descsz]
      build_id = note_content[-descsz:]
  
      with open(new_build_id_file, 'wb') as f:
        f.write(prefix + _ComputeNewBuildId(build_id, output_elf))
  
      # Write back the new build-id section.
      subprocess.check_call([
          objcopy,
          '--add-section',
          '{}={}'.format(build_id_section, new_build_id_file),
          # Add alloc section flag, or else the section will be removed by
          # objcopy --strip-all when generating unstripped lib file.
          '--set-section-flags',
          '{}={}'.format(build_id_section, 'alloc'),
          temp_elf,
          output_elf,
      ])
function_tokens: def _ExtractPartition ( objcopy , input_elf , output_elf , partition ) : if not partition : # main partition # We do not overwrite build-id on main partition to allow the expected # partition build ids to be synthesized given a libchrome.so binary, # if necessary. subprocess . check_call ( [ objcopy , '--extract-main-partition' , input_elf , output_elf ] ) return # partitioned libs build_id_section = '.note.gnu.build-id' with tempfile . TemporaryDirectory ( ) as tempdir : temp_elf = os . path . join ( tempdir , 'obj_without_id.so' ) old_build_id_file = os . path . join ( tempdir , 'old_build_id' ) new_build_id_file = os . path . join ( tempdir , 'new_build_id' ) # Dump out build-id section and remove original build-id section from # ELF file. subprocess . check_call ( [ objcopy , '--extract-partition' , partition , # Note: Not using '--update-section' here as it is not supported # by llvm-objcopy. '--remove-section' , build_id_section , '--dump-section' , '{}={}' . format ( build_id_section , old_build_id_file ) , input_elf , temp_elf , ] ) with open ( old_build_id_file , 'rb' ) as f : note_content = f . read ( ) # .note section has following format according to <elf/external.h> #   typedef struct { #       unsigned char   namesz[4];  /* Size of entry's owner string */ #       unsigned char   descsz[4];  /* Size of the note descriptor */ #       unsigned char   type[4];    /* Interpretation of the descriptor */ #       char        name[1];        /* Start of the name+desc data */ #   } Elf_External_Note; # `build-id` rewrite is only required on Android platform, # where we have partitioned lib. # Android platform uses little-endian. # <: little-endian # 4x: Skip 4 bytes # L: unsigned long, 4 bytes descsz , = struct . Struct ( '<4xL' ) . unpack_from ( note_content ) prefix = note_content [ : - descsz ] build_id = note_content [ - descsz : ] with open ( new_build_id_file , 'wb' ) as f : f . write ( prefix + _ComputeNewBuildId ( build_id , output_elf ) ) # Write back the new build-id section. subprocess . check_call ( [ objcopy , '--add-section' , '{}={}' . format ( build_id_section , new_build_id_file ) , # Add alloc section flag, or else the section will be removed by # objcopy --strip-all when generating unstripped lib file. '--set-section-flags' , '{}={}' . format ( build_id_section , 'alloc' ) , temp_elf , output_elf , ] )