Update patchelf.rb to 1.4.0

This commit is contained in:
Bo Anderson 2022-11-04 16:43:46 +00:00
parent a7c5e40c12
commit 031bd9cd18
No known key found for this signature in database
GPG Key ID: 3DB94E204E137D65
13 changed files with 315 additions and 77 deletions

View File

@ -84,8 +84,8 @@ GEM
sorbet-runtime (>= 0.5)
parser (3.1.2.1)
ast (~> 2.4.1)
patchelf (1.3.0)
elftools (>= 1.1.3)
patchelf (1.4.0)
elftools (>= 1.2)
plist (3.6.0)
pry (0.14.1)
coderay (~> 1.1)

View File

@ -13,17 +13,18 @@ module PatchELF::Helper
def alignup(val, align = T.unsafe(nil)); end
def color_enabled?; end
def colorize(str, type); end
def page_size(e_machine = T.unsafe(nil)); end
class << self
def aligndown(val, align = T.unsafe(nil)); end
def alignup(val, align = T.unsafe(nil)); end
def color_enabled?; end
def colorize(str, type); end
def page_size(e_machine = T.unsafe(nil)); end
end
end
PatchELF::Helper::COLOR_CODE = T.let(T.unsafe(nil), Hash)
PatchELF::Helper::PAGE_SIZE = T.let(T.unsafe(nil), Integer)
module PatchELF::Logger
private

View File

@ -80,7 +80,7 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rainbow-3.1.1/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-runtime-0.5.10461/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/parlour-8.0.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/patchelf-1.3.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/patchelf-1.4.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/plist-3.6.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/pry-0.14.1/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rack-3.0.0/lib")

View File

@ -11,7 +11,7 @@ require 'patchelf/helper'
# :nodoc:
module PatchELF
# TODO: refactor buf_* methods here
# TODO: move all refinements into a seperate file / helper file.
# TODO: move all refinements into a separate file / helper file.
# refinements for cleaner syntax / speed / memory optimizations
module Refinements
refine StringIO do
@ -21,7 +21,7 @@ module PatchELF
# @param [Integer] nbytes
# @return[void]
def fill(char, nbytes)
at_once = Helper::PAGE_SIZE
at_once = Helper.page_size
pending = nbytes
if pending > at_once
@ -133,6 +133,8 @@ module PatchELF
sec = find_section '.dynamic'
return unless sec
return if sec.header.sh_type == ELFTools::Constants::SHT_NOBITS
shdr = sec.header
with_buf_at(shdr.sh_offset) do |buf|
dyn = ELFTools::Structs::ELF_Dyn.new(elf_class: elf_class, endian: endian)
@ -171,7 +173,7 @@ module PatchELF
end
def modify_interpreter
@replaced_sections['.interp'] = @set[:interpreter] + "\x00"
@replaced_sections['.interp'] = "#{@set[:interpreter]}\x00"
end
def modify_needed
@ -234,14 +236,13 @@ module PatchELF
dyn_tags = collect_runpath_tags
resolve_rpath_tag_conflict(dyn_tags, force_rpath: force_rpath)
# (:runpath, :rpath) order_matters.
resolved_rpath_dyns = dyn_tags.values_at(:runpath, :rpath).compact
resolved_rpath_dyn = dyn_tags.values_at(:runpath, :rpath).compact.first
old_rpath = ''
rpath_off = nil
resolved_rpath_dyns.each do |dyn|
rpath_off = shdr_dynstr.sh_offset + dyn[:header].d_val
if resolved_rpath_dyn
rpath_off = shdr_dynstr.sh_offset + resolved_rpath_dyn[:header].d_val
old_rpath = buf_cstr(rpath_off)
break
end
return if old_rpath == new_rpath
@ -293,6 +294,11 @@ module PatchELF
dt_null_idx += 1
end
if dyn_num_bytes.nil?
Logger.error 'no dynamic tags'
return
end
# allot for new dt_runpath
shdr_dynamic = find_section('.dynamic').header
new_dynamic_data = replace_section '.dynamic', shdr_dynamic.sh_size + dyn_num_bytes
@ -331,7 +337,7 @@ module PatchELF
end
def page_size
Helper::PAGE_SIZE
Helper.page_size(ehdr.e_machine)
end
def patch_out
@ -359,7 +365,7 @@ module PatchELF
elsif data.size < size
data.ljust(size, "\x00")
else
data[0...size] + "\x00"
"#{data[0...size]}\x00"
end
@replaced_sections[section_name] = rep_data
end
@ -512,7 +518,7 @@ module PatchELF
def copy_shdrs_to_eof
shoff_new = @buffer.size
# honestly idk why `ehdr.e_shoff` is considered when we are only moving shdrs.
sh_size = ehdr.e_shoff + ehdr.e_shnum * ehdr.e_shentsize
sh_size = ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)
buf_grow! @buffer.size + sh_size
ehdr.e_shoff = shoff_new
raise PatchError, 'ehdr.e_shnum != @sections.size' if ehdr.e_shnum != @sections.size
@ -529,11 +535,11 @@ module PatchELF
def rewrite_sections_executable
sort_shdrs!
shdr = start_replacement_shdr
start_offset = shdr.sh_offset
start_addr = shdr.sh_addr
start_offset = shdr.sh_offset.to_i
start_addr = shdr.sh_addr.to_i
first_page = start_addr - start_offset
Logger.debug "first reserved offset/addr is 0x#{start_offset.to_i.to_s 16}/0x#{start_addr.to_i.to_s 16}"
Logger.debug "first reserved offset/addr is 0x#{start_offset.to_s 16}/0x#{start_addr.to_s 16}"
unless start_addr % page_size == start_offset % page_size
raise PatchError, 'start_addr != start_offset (mod PAGE_SIZE)'
@ -543,6 +549,8 @@ module PatchELF
copy_shdrs_to_eof if ehdr.e_shoff < start_offset
normalize_note_segments
seg_num_bytes = @segments.first.header.num_bytes
needed_space = (
ehdr.num_bytes +
@ -557,10 +565,10 @@ module PatchELF
Logger.debug "needed pages is #{needed_pages}"
raise PatchError, 'virtual address space underrun' if needed_pages * page_size > first_page
shift_file(needed_pages, start_offset)
first_page -= needed_pages * page_size
start_offset += needed_pages * page_size
shift_file(needed_pages, first_page)
end
Logger.debug "needed space is #{needed_space}"
@ -575,27 +583,31 @@ module PatchELF
end
def replace_sections_in_the_way_of_phdr!
pht_size = ehdr.num_bytes + (@segments.count + 1) * @segments.first.header.num_bytes
num_notes = @sections.count { |sec| sec.type == ELFTools::Constants::SHT_NOTE }
pht_size = ehdr.num_bytes + ((@segments.count + num_notes + 1) * @segments.first.header.num_bytes)
# replace sections that may overlap with expanded program header table
@sections.each_with_index do |sec, idx|
shdr = sec.header
next if idx.zero? || @replaced_sections[sec.name]
break if shdr.sh_addr > pht_size
break if shdr.sh_offset > pht_size
replace_section sec.name, shdr.sh_size
end
end
def seg_end_addr(seg)
def rewrite_sections_library
start_page = 0
first_page = 0
@segments.each do |seg|
phdr = seg.header
Helper.alignup(phdr.p_vaddr + phdr.p_memsz, page_size)
this_page = Helper.alignup(phdr.p_vaddr + phdr.p_memsz, page_size)
start_page = [start_page, this_page].max
first_page = phdr.p_vaddr - phdr.p_offset if phdr.p_type == ELFTools::Constants::PT_PHDR
end
def rewrite_sections_library
start_page = seg_end_addr(@segments.max_by(&method(:seg_end_addr)))
Logger.debug "Last page is 0x#{start_page.to_s 16}"
Logger.debug "First page is 0x#{first_page.to_s 16}"
replace_sections_in_the_way_of_phdr!
needed_space = @replaced_sections.sum { |_, str| Helper.alignup(str.size, @section_alignment) }
Logger.debug "needed space = #{needed_space}"
@ -623,42 +635,172 @@ module PatchELF
p_align: page_size
)
normalize_note_segments
cur_off = write_replaced_sections start_offset, start_page, start_offset
raise PatchError, 'cur_off != start_offset + needed_space' if cur_off != start_offset + needed_space
rewrite_headers ehdr.e_phoff
rewrite_headers(first_page + ehdr.e_phoff)
end
def shift_file(extra_pages, start_page)
oldsz = @buffer.size
shift = extra_pages * page_size
buf_grow!(oldsz + shift)
buf_move! shift, 0, oldsz
with_buf_at(ehdr.num_bytes) { |buf| buf.write "\x00" * (shift - ehdr.num_bytes) }
def normalize_note_segments
return if @replaced_sections.none? do |rsec_name, _|
find_section(rsec_name)&.type == ELFTools::Constants::SHT_NOTE
end
ehdr.e_phoff = ehdr.num_bytes
ehdr.e_shoff = ehdr.e_shoff + shift
new_phdrs = []
phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr|
# Binaries produced by older patchelf versions may contain empty PT_NOTE segments.
next if @sections.none? do |sec|
sec.header.sh_offset >= phdr.p_offset && sec.header.sh_offset < phdr.p_offset + phdr.p_filesz
end
new_phdrs += normalize_note_segment(phdr)
end
new_phdrs.each { |phdr| add_segment!(**phdr.snapshot) }
end
def normalize_note_segment(phdr)
start_off = phdr.p_offset.to_i
curr_off = start_off
end_off = start_off + phdr.p_filesz
new_phdrs = []
while curr_off < end_off
size = 0
sections_at_aligned_offset(curr_off) do |sec|
next if sec.type != ELFTools::Constants::SHT_NOTE
size = sec.header.sh_size.to_i
curr_off = sec.header.sh_offset.to_i
break
end
raise PatchError, 'cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections' if size.zero?
if curr_off + size > end_off
raise PatchError, 'cannot normalize PT_NOTE segment: partially mapped SHT_NOTE section'
end
new_phdr = ELFTools::Structs::ELF_Phdr[elf_class].new(endian: endian, **phdr.snapshot)
new_phdr.p_offset = curr_off
new_phdr.p_vaddr = phdr.p_vaddr + (curr_off - start_off)
new_phdr.p_paddr = phdr.p_paddr + (curr_off - start_off)
new_phdr.p_filesz = size
new_phdr.p_memsz = size
if curr_off == start_off
phdr.assign(new_phdr)
else
new_phdrs << new_phdr
end
curr_off += size
end
new_phdrs
end
def sections_at_aligned_offset(offset)
@sections.each do |sec|
shdr = sec.header
aligned_offset = Helper.alignup(offset, shdr.sh_addralign)
next if shdr.sh_offset != aligned_offset
yield sec
end
end
def shift_sections(shift, start_offset)
ehdr.e_shoff += shift if ehdr.e_shoff >= start_offset
@sections.each_with_index do |sec, i|
next if i.zero? # dont touch NULL section
shdr = sec.header
next if shdr.sh_offset < start_offset
shdr.sh_offset += shift
end
end
@segments.each do |seg|
phdr = seg.header
def shift_segment_offset(phdr, shift)
phdr.p_offset += shift
phdr.p_align = page_size if phdr.p_align != 0 && (phdr.p_vaddr - phdr.p_offset) % phdr.p_align != 0
end
def shift_segment_virtual_address(phdr, shift)
phdr.p_paddr -= shift if phdr.p_paddr > shift
phdr.p_vaddr -= shift if phdr.p_vaddr > shift
end
# rubocop:disable Metrics/PerceivedComplexity
def shift_segments(shift, start_offset)
split_index = -1
split_shift = 0
@segments.each_with_index do |seg, idx|
phdr = seg.header
p_start = phdr.p_offset
if p_start <= start_offset && p_start + phdr.p_filesz > start_offset &&
phdr.p_type == ELFTools::Constants::PT_LOAD
raise PatchError, "split_index(#{split_index}) != -1" if split_index != -1
split_index = idx
split_shift = start_offset - p_start
phdr.p_offset = start_offset
phdr.p_memsz -= split_shift
phdr.p_filesz -= split_shift
phdr.p_paddr += split_shift
phdr.p_vaddr += split_shift
p_start = start_offset
end
if p_start >= start_offset
shift_segment_offset(phdr, shift)
else
shift_segment_virtual_address(phdr, shift)
end
end
raise PatchError, "split_index(#{split_index}) == -1" if split_index == -1
[split_index, split_shift]
end
# rubocop:enable Metrics/PerceivedComplexity
def shift_file(extra_pages, start_offset)
raise PatchError, "start_offset(#{start_offset}) < ehdr.num_bytes" if start_offset < ehdr.num_bytes
oldsz = @buffer.size
raise PatchError, "oldsz <= start_offset(#{start_offset})" if oldsz <= start_offset
shift = extra_pages * page_size
buf_grow!(oldsz + shift)
buf_move!(start_offset + shift, start_offset, oldsz - start_offset)
with_buf_at(start_offset) { |buf| buf.write "\x00" * shift }
ehdr.e_phoff = ehdr.num_bytes
shift_sections(shift, start_offset)
split_index, split_shift = shift_segments(shift, start_offset)
split_phdr = @segments[split_index].header
add_segment!(
p_type: ELFTools::Constants::PT_LOAD,
p_offset: 0,
p_vaddr: start_page,
p_paddr: start_page,
p_filesz: shift,
p_memsz: shift,
p_offset: split_phdr.p_offset - split_shift - shift,
p_vaddr: split_phdr.p_vaddr - split_shift - shift,
p_paddr: split_phdr.p_paddr - split_shift - shift,
p_filesz: split_shift + shift,
p_memsz: split_shift + shift,
p_flags: ELFTools::Constants::PF_R | ELFTools::Constants::PF_W,
p_align: page_size
)
@ -699,12 +841,23 @@ module PatchELF
end
def sort_shdrs!
return if @sections.empty?
section_dep_values = collect_section_to_section_refs
shstrtab_name = @sections[ehdr.e_shstrndx].name
shstrtab = @sections[ehdr.e_shstrndx].header
@sections.sort! { |me, you| me.header.sh_offset.to_i <=> you.header.sh_offset.to_i }
update_section_idx!
restore_section_to_section_refs!(section_dep_values)
ehdr.e_shstrndx = find_section_idx shstrtab_name
@sections.each_with_index do |sec, idx|
ehdr.e_shstrndx = idx if sec.header.sh_offset == shstrtab.sh_offset
end
end
def jmprel_section_name
sec_name = %w[.rel.plt .rela.plt .rela.IA_64.pltoff].find { |s| find_section(s) }
raise PatchError, 'cannot find section corresponding to DT_JMPREL' unless sec_name
sec_name
end
# given a +dyn.d_tag+, returns the section name it must be synced to.
@ -719,12 +872,14 @@ module PatchELF
when ELFTools::Constants::DT_HASH
'.hash'
when ELFTools::Constants::DT_GNU_HASH
'.gnu.hash'
when ELFTools::Constants::DT_JMPREL
sec_name = %w[.rel.plt .rela.plt .rela.IA_64.pltoff].find { |s| find_section(s) }
raise PatchError, 'cannot find section corresponding to DT_JMPREL' unless sec_name
# return nil if not found, patchelf claims no problem in skipping
find_section('.gnu.hash')&.name
when ELFTools::Constants::DT_MIPS_XHASH
return if ehdr.e_machine != ELFTools::Constants::EM_MIPS
sec_name
'.MIPS.xhash'
when ELFTools::Constants::DT_JMPREL
jmprel_section_name
when ELFTools::Constants::DT_REL
# regarding .rel.got, NixOS/patchelf says
# "no idea if this makes sense, but it was needed for some program"
@ -743,9 +898,26 @@ module PatchELF
# updates dyn tags by syncing it with @section values
def sync_dyn_tags!
dyn_table_offset = nil
each_dynamic_tags do |dyn, buf_off|
dyn_table_offset ||= buf_off
sec_name = dyn_tag_to_section_name(dyn.d_tag)
next unless sec_name
unless sec_name
if dyn.d_tag == ELFTools::Constants::DT_MIPS_RLD_MAP_REL && ehdr.e_machine == ELFTools::Constants::EM_MIPS
rld_map = find_section('.rld_map')
dyn.d_val = if rld_map
rld_map.header.sh_addr.to_i - (buf_off - dyn_table_offset) -
find_section('.dynamic').header.sh_addr.to_i
else
Logger.warn 'DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not'
0
end
end
next
end
shdr = find_section(sec_name).header
dyn.d_val = dyn.d_tag == ELFTools::Constants::DT_STRSZ ? shdr.sh_size.to_i : shdr.sh_addr.to_i
@ -784,22 +956,46 @@ module PatchELF
end
end
def write_replaced_sections(cur_off, start_addr, start_offset)
sht_no_bits = ELFTools::Constants::SHT_NOBITS
# Returns a blank shdr if the section doesn't exist.
def find_or_create_section_header(rsec_name)
shdr = find_section(rsec_name)&.header
shdr ||= ELFTools::Structs::ELF_Shdr.new(endian: endian, elf_class: elf_class)
shdr
end
# the original source says this has to be done seperately to
def overwrite_replaced_sections
# the original source says this has to be done separately to
# prevent clobbering the previously written section contents.
@replaced_sections.each do |rsec_name, _|
shdr = find_section(rsec_name).header
with_buf_at(shdr.sh_offset) { |b| b.fill('X', shdr.sh_size) } if shdr.sh_type != sht_no_bits
shdr = find_section(rsec_name)&.header
next unless shdr
next if shdr.sh_type == ELFTools::Constants::SHT_NOBITS
with_buf_at(shdr.sh_offset) { |b| b.fill('X', shdr.sh_size) }
end
end
def write_section_aligment(shdr)
return if shdr.sh_type == ELFTools::Constants::SHT_NOTE && shdr.sh_addralign <= @section_alignment
shdr.sh_addralign = @section_alignment
end
def section_bounds_within_segment?(s_start, s_end, p_start, p_end)
(s_start >= p_start && s_start < p_end) || (s_end > p_start && s_end <= p_end)
end
def write_replaced_sections(cur_off, start_addr, start_offset)
overwrite_replaced_sections
noted_phdrs = Set.new
# the sort is necessary, the strategy in ruby and Cpp to iterate map/hash
# is different, patchelf v0.10 iterates the replaced_sections sorted by
# keys.
@replaced_sections.sort.each do |rsec_name, rsec_data|
section = find_section(rsec_name)
shdr = section.header
shdr = find_or_create_section_header(rsec_name)
Logger.debug <<~DEBUG
rewriting section '#{rsec_name}'
@ -809,18 +1005,43 @@ module PatchELF
with_buf_at(cur_off) { |b| b.write rsec_data }
orig_sh_offset = shdr.sh_offset.to_i
orig_sh_size = shdr.sh_size.to_i
shdr.sh_offset = cur_off
shdr.sh_addr = start_addr + (cur_off - start_offset)
shdr.sh_size = rsec_data.size
shdr.sh_addralign = @section_alignment
write_section_aligment(shdr)
seg_type = {
'.interp' => ELFTools::Constants::PT_INTERP,
'.dynamic' => ELFTools::Constants::PT_DYNAMIC
}[section.name]
'.dynamic' => ELFTools::Constants::PT_DYNAMIC,
'.MIPS.abiflags' => ELFTools::Constants::PT_MIPS_ABIFLAGS,
'.note.gnu.property' => ELFTools::Constants::PT_GNU_PROPERTY
}[rsec_name]
phdrs_by_type(seg_type) { |phdr| sync_sec_to_seg(shdr, phdr) }
if shdr.sh_type == ELFTools::Constants::SHT_NOTE
phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr, idx|
next if noted_phdrs.include?(idx)
s_start = orig_sh_offset
s_end = s_start + orig_sh_size
p_start = phdr.p_offset
p_end = p_start + phdr.p_filesz
next unless section_bounds_within_segment?(s_start, s_end, p_start, p_end)
raise PatchError, 'unsupported overlap of SHT_NOTE and PT_NOTE' if p_start != s_start || p_end != s_end
sync_sec_to_seg(shdr, phdr)
noted_phdrs << idx
end
end
cur_off += Helper.alignup(rsec_data.size, @section_alignment)
end
@replaced_sections.clear

View File

@ -139,7 +139,7 @@ module PatchELF
@options[:set][:soname] = soname
end
opts.on('--version', 'Show current gem\'s version.') {}
opts.on('--version', 'Show current gem\'s version.')
end
end

View File

@ -6,8 +6,10 @@ require 'elftools/exceptions'
module PatchELF
# Raised on an error during ELF modification.
class PatchError < ELFTools::ELFError; end
# Raised when Dynamic Tag is missing
class MissingTagError < PatchError; end
# Raised on missing Program Header(segment)
class MissingSegmentError < PatchError; end
end

View File

@ -3,9 +3,6 @@
module PatchELF
# Helper methods for internal usage.
module Helper
# The size of one page.
PAGE_SIZE = 0x1000
module_function
# Color codes for pretty print.
@ -16,6 +13,23 @@ module PatchELF
error: "\e[38;5;196m" # heavy red
}.freeze
# The size of one page.
def page_size(e_machine = nil)
# Different architectures have different minimum section alignments.
case e_machine
when ELFTools::Constants::EM_SPARC,
ELFTools::Constants::EM_MIPS,
ELFTools::Constants::EM_PPC,
ELFTools::Constants::EM_PPC64,
ELFTools::Constants::EM_AARCH64,
ELFTools::Constants::EM_TILEGX,
ELFTools::Constants::EM_LOONGARCH
0x10000
else
0x1000
end
end
# For wrapping string with color codes for prettier inspect.
# @param [String] str
# Content to colorize.
@ -48,7 +62,7 @@ module PatchELF
# #=> 32
# aligndown(0x10, 0x8)
# #=> 16
def aligndown(val, align = PAGE_SIZE)
def aligndown(val, align = page_size)
val - (val & (align - 1))
end
@ -63,7 +77,7 @@ module PatchELF
# #=> 64
# alignup(0x10, 0x8)
# #=> 16
def alignup(val, align = PAGE_SIZE)
def alignup(val, align = page_size)
(val & (align - 1)).zero? ? val : (aligndown(val, align) + align)
end
end

View File

@ -115,7 +115,7 @@ module PatchELF
# prefer backward than forward
return extend_backward(loads[idx - 1]) if writable?(loads[idx - 1])
# note: loads[idx].file_head has been changed in shift_attributes
# NOTE: loads[idx].file_head has been changed in shift_attributes
extend_forward(loads[idx], @extend_size)
end
@ -161,7 +161,7 @@ module PatchELF
seg.header.p_offset += extend_size
# We have to change align of LOAD segment since ld.so checks it.
seg.header.p_align = Helper::PAGE_SIZE if seg.is_a?(ELFTools::Segments::LoadSegment)
seg.header.p_align = Helper.page_size if seg.is_a?(ELFTools::Segments::LoadSegment)
end
@elf.header.e_shoff += extend_size if @elf.header.e_shoff >= threshold

View File

@ -30,7 +30,7 @@ module PatchELF
@elf = ELFTools::ELFFile.new(File.open(filename))
@set = {}
@rpath_sym = :runpath
@on_error = !logging ? :exception : on_error
@on_error = logging ? on_error : :exception
on_error_syms = %i[exception log silent]
raise ArgumentError, "on_error must be one of #{on_error_syms}" unless on_error_syms.include?(@on_error)

View File

@ -53,8 +53,8 @@ module PatchELF
def patch_interpreter
return if @set[:interpreter].nil?
new_interp = @set[:interpreter] + "\x00"
old_interp = @elf.segment_by_type(:interp).interp_name + "\x00"
new_interp = "#{@set[:interpreter]}\x00"
old_interp = "#{@elf.segment_by_type(:interp).interp_name}\x00"
return if old_interp == new_interp
# These headers must be found here but not in the proc.
@ -184,7 +184,7 @@ module PatchELF
need_size = strtab_string.size + @strtab_extend_requests.reduce(0) { |sum, (str, _)| sum + str.size + 1 }
dynstr = section_header('.dynstr')
@mm.malloc(need_size) do |off, vaddr|
new_str = strtab_string + @strtab_extend_requests.map(&:first).join("\x00") + "\x00"
new_str = "#{strtab_string}#{@strtab_extend_requests.map(&:first).join("\x00")}\x00"
inline_patch(off, new_str)
cur = strtab_string.size
@strtab_extend_requests.each do |str, block|
@ -206,7 +206,7 @@ module PatchELF
# @yieldparam [Integer] idx
# @yieldreturn [void]
def reg_str_table(str, &block)
idx = strtab_string.index(str + "\x00")
idx = strtab_string.index("#{str}\x00")
# Request string is already exist
return yield idx if idx

View File

@ -2,5 +2,5 @@
module PatchELF
# Current gem version.
VERSION = '1.3.0'.freeze
VERSION = '1.4.0'.freeze
end