patchelf 1.5.2 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f11434b437c5d8623134c6c1fe78332b8cbc1251bfd1b0549a560fef7160cf1e
4
- data.tar.gz: 742bade914a5ad4e8b1523ad3d1aea9b2a801f89365e087cbc2d7fed0bfe4cba
3
+ metadata.gz: 72b60be48f5040899d73767baf55e3e4338578e3301c91116a9769a396f28788
4
+ data.tar.gz: 454399ea53bcbd52931102451dfaac13da564ded12675829e92b80eff77668f2
5
5
  SHA512:
6
- metadata.gz: a476877469a6480b277ac318e703eb8d5a5c373b47b095b5c215327207e52b024fc8c38093ef3974fb022f206078c4ae20548d97d861bcc3bcae3e5a0b6727c6
7
- data.tar.gz: 4acd3a4e025dec84cefe1b45d09f6aa5425618a12ac3f5bb94a60a3aa9f04a9e5fba68cba8f988be6866a615744ae1f03c3a944812a12513bb4612ade87aa721
6
+ metadata.gz: d8741f0b203ce8592936f3305305214fff490f64caa145dda380e3d65cbc95809868871c137ef68a674956438a3ea7eac8640b68707ad7146d98f5c90170fedb
7
+ data.tar.gz: b903bcccd2d07f03470c3915616f26b0d98027c5ffe79c63578b2aa1feb25123a990ea9617f4cc6b4d8796d3caf7832fe2aa6b5e8d52d91e89d9a4700a24497d
data/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  [![Downloads](https://img.shields.io/endpoint?url=https://gem-badge-h3lg.onrender.com/downloads/patchelf)](https://rubygems.org/gems/patchelf)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/patchelf.svg)](https://badge.fury.io/rb/patchelf)
4
- [![Build Status](https://github.com/david942j/patchelf.rb/workflows/build/badge.svg)](https://github.com/david942j/patchelf.rb/actions)
5
- [![Maintainability](https://qlty.sh/gh/david942j/projects/patchelf.rb/maintainability.svg)](https://qlty.sh/gh/david942j/projects/patchelf.rb)
6
- [![Code Coverage](https://qlty.sh/gh/david942j/projects/patchelf.rb/coverage.svg)](https://qlty.sh/gh/david942j/projects/patchelf.rb)
7
- [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/david942j/patchelf.rb/master)
8
- [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](http://choosealicense.com/licenses/mit/)
4
+ [![CI](https://github.com/Homebrew/patchelf.rb/actions/workflows/tests.yml/badge.svg)](https://github.com/Homebrew/patchelf.rb/actions/workflows/tests.yml)
5
+ [![Coverage Status](https://codecov.io/gh/Homebrew/patchelf.rb/graph/badge.svg)](https://codecov.io/gh/Homebrew/patchelf.rb)
6
+ [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/patchelf)
7
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://choosealicense.com/licenses/mit/)
9
8
 
10
9
  # patchelf.rb
11
10
 
@@ -136,3 +135,16 @@ patcher.save('ls.patch')
136
135
  ## Environment
137
136
 
138
137
  patchelf.rb is implemented in pure Ruby, so it should work in all environments include Linux, macOS, and Windows!
138
+
139
+ ## Project Authors
140
+
141
+ The git history remains the definitive record of all contributions.
142
+
143
+ ### Original Author and Project Founder
144
+
145
+ * david942j (@david942j)
146
+
147
+ ### Maintainers
148
+
149
+ * Homebrew maintainers
150
+ * david942j (@david942j)
@@ -58,7 +58,7 @@ module PatchELF
58
58
  @out_file = out_file
59
59
  @set = set
60
60
 
61
- f = File.open(in_file, 'rb')
61
+ f = File.open(in_file, 'rb') # rubocop:disable Style/FileOpen
62
62
  # the +@buffer+ and +@elf+ both could work on same +StringIO+ stream,
63
63
  # the updating of @buffer in place blocks us from looking up old values.
64
64
  # TODO: cache the values needed later, use same stream for +@buffer+ and +@elf+.
@@ -130,14 +130,12 @@ module PatchELF
130
130
  find_section '.dynstr'
131
131
  end
132
132
 
133
- # yields dynamic tag, and offset in buffer
133
+ # Yields dynamic tag, and its offset in @buffer.
134
+ # @yieldparam [ELFTools::Structs::ELF_Dyn] dyn
135
+ # @yieldparam [Integer] offset The offset of this dynamic tag within +@buffer+.
134
136
  def each_dynamic_tags
135
- return unless block_given?
136
-
137
- sec = find_section '.dynamic'
138
- return unless sec
139
-
140
- return if sec.header.sh_type == ELFTools::Constants::SHT_NOBITS
137
+ sec = find_section('.dynamic')
138
+ return if sec.nil? || sec.header.sh_type == ELFTools::Constants::SHT_NOBITS
141
139
 
142
140
  shdr = sec.header
143
141
  with_buf_at(shdr.sh_offset) do |buf|
@@ -149,8 +147,8 @@ module PatchELF
149
147
  break if dyn.d_tag == ELFTools::Constants::DT_NULL
150
148
 
151
149
  yield dyn, buf_dyn_offset
152
- # there's a possibility for caller to modify @buffer.pos, seek to avoid such issues
153
- buf.seek buf_dyn_offset + dyn.num_bytes
150
+ # It's possible the caller may modify @buffer.pos, seek to ensure it points to the next tag.
151
+ buf.seek(buf_dyn_offset + dyn.num_bytes)
154
152
  end
155
153
  end
156
154
  end
@@ -675,18 +673,13 @@ module PatchELF
675
673
  new_phdrs = []
676
674
 
677
675
  while curr_off < end_off
678
- size = 0
679
- sections_at_aligned_offset(curr_off) do |sec|
680
- next if sec.type != ELFTools::Constants::SHT_NOTE
681
-
682
- size = sec.header.sh_size.to_i
683
- curr_off = sec.header.sh_offset.to_i
684
- break
685
- end
676
+ section = sections_at_aligned_offset(curr_off).find { |sec| sec.type == ELFTools::Constants::SHT_NOTE }
677
+ raise PatchError, 'cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections' if section.nil?
686
678
 
687
- raise PatchError, 'cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections' if size.zero?
679
+ size = section.header.sh_size.to_i
680
+ curr_off = section.header.sh_offset.to_i
688
681
 
689
- if curr_off + size > end_off
682
+ if size.zero? || curr_off + size > end_off
690
683
  raise PatchError, 'cannot normalize PT_NOTE segment: partially mapped SHT_NOTE section'
691
684
  end
692
685
 
@@ -710,6 +703,8 @@ module PatchELF
710
703
  end
711
704
 
712
705
  def sections_at_aligned_offset(offset)
706
+ return to_enum(__method__, offset) unless block_given?
707
+
713
708
  @sections.each do |sec|
714
709
  shdr = sec.header
715
710
 
@@ -743,7 +738,6 @@ module PatchELF
743
738
  phdr.p_vaddr -= shift if phdr.p_vaddr > shift
744
739
  end
745
740
 
746
- # rubocop:disable Metrics/PerceivedComplexity
747
741
  def shift_segments(shift, start_offset)
748
742
  split_index = -1
749
743
  split_shift = 0
@@ -752,9 +746,8 @@ module PatchELF
752
746
  phdr = seg.header
753
747
  p_start = phdr.p_offset
754
748
 
755
- if p_start <= start_offset && p_start + phdr.p_filesz > start_offset &&
756
- phdr.p_type == ELFTools::Constants::PT_LOAD
757
- raise PatchError, "split_index(#{split_index}) != -1" if split_index != -1
749
+ if (p_start...(p_start + phdr.p_filesz)).cover?(start_offset) && phdr.p_type == ELFTools::Constants::PT_LOAD
750
+ raise PatchError, 'PT_LOAD segments overlapped, unable to shift segments' if split_index != -1
758
751
 
759
752
  split_index = idx
760
753
  split_shift = start_offset - p_start
@@ -775,11 +768,10 @@ module PatchELF
775
768
  end
776
769
  end
777
770
 
778
- raise PatchError, "split_index(#{split_index}) == -1" if split_index == -1
771
+ raise PatchError, "No PT_LOAD found covers offset 0x#{start_offset.to_s(16)}" if split_index == -1
779
772
 
780
773
  [split_index, split_shift]
781
774
  end
782
- # rubocop:enable Metrics/PerceivedComplexity
783
775
 
784
776
  def shift_file(extra_pages, start_offset, extra_bytes)
785
777
  raise PatchError, "start_offset(#{start_offset}) < ehdr.num_bytes" if start_offset < ehdr.num_bytes
@@ -865,9 +857,9 @@ module PatchELF
865
857
  sec_name
866
858
  end
867
859
 
868
- # given a +dyn.d_tag+, returns the section name it must be synced to.
869
- # it may return nil, when given tag maps to no section,
870
- # or when its okay to skip if section is not found.
860
+ # Given a +dyn.d_tag+, returns the section name it must be synced to.
861
+ # Returns +nil+ when given tag maps to no section, or when its okay to skip if section is not found.
862
+ # @return [String?]
871
863
  def dyn_tag_to_section_name(d_tag)
872
864
  case d_tag
873
865
  when ELFTools::Constants::DT_STRTAB, ELFTools::Constants::DT_STRSZ
@@ -901,32 +893,37 @@ module PatchELF
901
893
  end
902
894
  end
903
895
 
896
+ # @return [ELFTools::Structs::ELF_Shdr?]
897
+ def dyn_tag_to_shdr(d_tag)
898
+ sec_name = dyn_tag_to_section_name(d_tag)
899
+ return if sec_name.nil?
900
+
901
+ find_section(sec_name)&.header
902
+ end
903
+
904
904
  # updates dyn tags by syncing it with @section values
905
905
  def sync_dyn_tags!
906
+ # Position of the fist dynamic tag.
906
907
  dyn_table_offset = nil
907
908
  each_dynamic_tags do |dyn, buf_off|
908
909
  dyn_table_offset ||= buf_off
909
910
 
910
- sec_name = dyn_tag_to_section_name(dyn.d_tag)
911
-
912
- unless sec_name
913
- if dyn.d_tag == ELFTools::Constants::DT_MIPS_RLD_MAP_REL && ehdr.e_machine == ELFTools::Constants::EM_MIPS
914
- rld_map = find_section('.rld_map')
915
- dyn.d_val = if rld_map
916
- rld_map.header.sh_addr.to_i - (buf_off - dyn_table_offset) -
917
- find_section('.dynamic').header.sh_addr.to_i
918
- else
919
- Logger.warn 'DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not'
920
- 0
921
- end
922
- end
911
+ if dyn.d_tag == ELFTools::Constants::DT_MIPS_RLD_MAP_REL
912
+ rld_map = find_section('.rld_map')
913
+ dyn.d_val = if rld_map
914
+ rld_map.header.sh_addr.to_i - (buf_off - dyn_table_offset) -
915
+ find_section('.dynamic').header.sh_addr.to_i
916
+ else
917
+ Logger.warn 'DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not'
918
+ 0
919
+ end
920
+ else
921
+ shdr = dyn_tag_to_shdr(dyn.d_tag)
922
+ next if shdr.nil?
923
923
 
924
- next
924
+ dyn.d_val = dyn.d_tag == ELFTools::Constants::DT_STRSZ ? shdr.sh_size.to_i : shdr.sh_addr.to_i
925
925
  end
926
926
 
927
- shdr = find_section(sec_name).header
928
- dyn.d_val = dyn.d_tag == ELFTools::Constants::DT_STRSZ ? shdr.sh_size.to_i : shdr.sh_addr.to_i
929
-
930
927
  with_buf_at(buf_off) { |wbuf| dyn.write(wbuf) }
931
928
  end
932
929
  end
@@ -945,6 +942,8 @@ module PatchELF
945
942
  nil
946
943
  end
947
944
 
945
+ # Some sections have their corresponding segment.
946
+ # Use this utility when a section is being patched so its segment should be updated with the same values.
948
947
  def sync_sec_to_seg(shdr, phdr)
949
948
  phdr.p_offset = shdr.sh_offset.to_i
950
949
  phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr.to_i
@@ -962,6 +961,8 @@ module PatchELF
962
961
  end
963
962
 
964
963
  # Returns a blank shdr if the section doesn't exist.
964
+ #
965
+ # @return [ELFTools::Structs::ELF_Shdr]
965
966
  def find_or_create_section_header(rsec_name)
966
967
  shdr = find_section(rsec_name)&.header
967
968
  shdr ||= ELFTools::Structs::ELF_Shdr.new(endian: endian, elf_class: elf_class)
@@ -991,11 +992,54 @@ module PatchELF
991
992
  (s_start >= p_start && s_start < p_end) || (s_end > p_start && s_end <= p_end)
992
993
  end
993
994
 
995
+ # Used when patching sections.
996
+ # For sections with a correspondence segment, update the segment values.
997
+ # @return [void]
998
+ def section_sync_correspondence_segment(sec_name, shdr)
999
+ seg_type = {
1000
+ '.interp' => ELFTools::Constants::PT_INTERP,
1001
+ '.dynamic' => ELFTools::Constants::PT_DYNAMIC,
1002
+ '.MIPS.abiflags' => ELFTools::Constants::PT_MIPS_ABIFLAGS,
1003
+ '.note.gnu.property' => ELFTools::Constants::PT_GNU_PROPERTY
1004
+ }[sec_name]
1005
+ return if seg_type.nil?
1006
+
1007
+ phdrs_by_type(seg_type) { |phdr| sync_sec_to_seg(shdr, phdr) }
1008
+ end
1009
+
1010
+ # Similar to +section_sync_correspondence_segment+ but dedicate for note sections as it is allowed to have multiple
1011
+ # note segments.
1012
+ # This function searches all note segments and only sync the one matched with the section values before patching.
1013
+ #
1014
+ # NOTE: This function is no-op if +shdr+ does not have section type +ELFTools::Constants::SHT_NOTE+.
1015
+ #
1016
+ # @param [Integer] orig_sh_offset The original section offset value.
1017
+ # @param [Integer] orig_sh_size The original section size value.
1018
+ # @param [ELFTools::Structs::ELF_Shdr] shdr The section header with values after patched.
1019
+ #
1020
+ # @return [void]
1021
+ def sync_note_segment(orig_sh_offset, orig_sh_size, shdr)
1022
+ return if shdr.sh_type != ELFTools::Constants::SHT_NOTE
1023
+
1024
+ phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr|
1025
+ s_start = orig_sh_offset
1026
+ s_end = s_start + orig_sh_size
1027
+ p_start = phdr.p_offset
1028
+ p_end = p_start + phdr.p_filesz
1029
+
1030
+ # Skip if no overlap.
1031
+ next unless section_bounds_within_segment?(s_start, s_end, p_start, p_end)
1032
+
1033
+ # Only support exact matches.
1034
+ raise PatchError, 'unsupported overlap of SHT_NOTE and PT_NOTE' unless [p_start, p_end] == [s_start, s_end]
1035
+
1036
+ sync_sec_to_seg(shdr, phdr)
1037
+ end
1038
+ end
1039
+
994
1040
  def write_replaced_sections(cur_off, start_addr, start_offset)
995
1041
  overwrite_replaced_sections
996
1042
 
997
- noted_phdrs = Set.new
998
-
999
1043
  # the sort is necessary, the strategy in ruby and Cpp to iterate map/hash
1000
1044
  # is different, patchelf v0.10 iterates the replaced_sections sorted by
1001
1045
  # keys.
@@ -1018,34 +1062,8 @@ module PatchELF
1018
1062
  shdr.sh_size = rsec_data.size
1019
1063
 
1020
1064
  write_section_alignment(shdr)
1021
-
1022
- seg_type = {
1023
- '.interp' => ELFTools::Constants::PT_INTERP,
1024
- '.dynamic' => ELFTools::Constants::PT_DYNAMIC,
1025
- '.MIPS.abiflags' => ELFTools::Constants::PT_MIPS_ABIFLAGS,
1026
- '.note.gnu.property' => ELFTools::Constants::PT_GNU_PROPERTY
1027
- }[rsec_name]
1028
-
1029
- phdrs_by_type(seg_type) { |phdr| sync_sec_to_seg(shdr, phdr) }
1030
-
1031
- if shdr.sh_type == ELFTools::Constants::SHT_NOTE
1032
- phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr, idx|
1033
- next if noted_phdrs.include?(idx)
1034
-
1035
- s_start = orig_sh_offset
1036
- s_end = s_start + orig_sh_size
1037
- p_start = phdr.p_offset
1038
- p_end = p_start + phdr.p_filesz
1039
-
1040
- next unless section_bounds_within_segment?(s_start, s_end, p_start, p_end)
1041
-
1042
- raise PatchError, 'unsupported overlap of SHT_NOTE and PT_NOTE' if p_start != s_start || p_end != s_end
1043
-
1044
- sync_sec_to_seg(shdr, phdr)
1045
-
1046
- noted_phdrs << idx
1047
- end
1048
- end
1065
+ section_sync_correspondence_segment(rsec_name, shdr)
1066
+ sync_note_segment(orig_sh_offset, orig_sh_size, shdr)
1049
1067
 
1050
1068
  cur_off += Helper.alignup(rsec_data.size, @section_alignment)
1051
1069
  end
data/lib/patchelf/cli.rb CHANGED
@@ -9,7 +9,7 @@ module PatchELF
9
9
  # For command line interface to parsing arguments.
10
10
  module CLI
11
11
  # Name of binary.
12
- SCRIPT_NAME = 'patchelf.rb'.freeze
12
+ SCRIPT_NAME = 'patchelf.rb'
13
13
  # CLI usage string.
14
14
  USAGE = format('Usage: %s <commands> FILENAME [OUTPUT_FILE]', SCRIPT_NAME).freeze
15
15
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'elftools/constants'
4
+
3
5
  module PatchELF
4
6
  # Helper methods for internal usage.
5
7
  module Helper
@@ -17,7 +19,8 @@ module PatchELF
17
19
  def page_size(e_machine = nil)
18
20
  # Different architectures have different minimum section alignments.
19
21
  case e_machine
20
- when ELFTools::Constants::EM_SPARC,
22
+ when ELFTools::Constants::EM_ALPHA,
23
+ ELFTools::Constants::EM_IA_64,
21
24
  ELFTools::Constants::EM_MIPS,
22
25
  ELFTools::Constants::EM_PPC,
23
26
  ELFTools::Constants::EM_PPC64,
@@ -25,6 +28,9 @@ module PatchELF
25
28
  ELFTools::Constants::EM_TILEGX,
26
29
  ELFTools::Constants::EM_LOONGARCH
27
30
  0x10000
31
+ when ELFTools::Constants::EM_SPARC,
32
+ ELFTools::Constants::EM_SPARCV9
33
+ 0x2000
28
34
  else
29
35
  0x1000
30
36
  end
data/lib/patchelf/mm.rb CHANGED
@@ -105,12 +105,19 @@ module PatchELF
105
105
  #=>
106
106
  # | 1 | | 2 |
107
107
  # | 1 | | 2 |
108
- idx = find_gap(check_sz: false) { |prv, nxt| PatchELF::Helper.aligndown(nxt.mem_head) - prv.mem_tail }
108
+ extension = PatchELF::Helper.alignup(@request_size, page_size)
109
+ idx = find_gap(check_sz: false) do |prv, nxt|
110
+ gap = PatchELF::Helper.aligndown(nxt.mem_head, page_size) - prv.mem_tail
111
+ # Forward growth moves the entire mapping back by the rounded extension.
112
+ next 0 if !writable?(prv) && gap < extension
113
+
114
+ gap
115
+ end
109
116
  return false if idx.nil?
110
117
 
111
118
  loads = load_segments
112
119
  @threshold = loads[idx].file_head
113
- @extend_size = PatchELF::Helper.alignup(@request_size)
120
+ @extend_size = extension
114
121
  shift_attributes
115
122
  # prefer backward than forward
116
123
  return extend_backward?(loads[idx - 1]) if writable?(loads[idx - 1])
@@ -160,8 +167,12 @@ module PatchELF
160
167
  next unless seg.header.p_offset >= threshold
161
168
 
162
169
  seg.header.p_offset += extend_size
163
- # We have to change align of LOAD segment since ld.so checks it.
164
- seg.header.p_align = Helper.page_size if seg.is_a?(ELFTools::Segments::LoadSegment)
170
+ # Preserve a valid alignment; ld.so requires LOAD addresses to be congruent.
171
+ next unless seg.is_a?(ELFTools::Segments::LoadSegment) &&
172
+ seg.header.p_align.nonzero? &&
173
+ ((seg.header.p_vaddr - seg.header.p_offset) % seg.header.p_align).nonzero?
174
+
175
+ seg.header.p_align = page_size
165
176
  end
166
177
 
167
178
  @elf.header.e_shoff += extend_size if @elf.header.e_shoff >= threshold
@@ -179,6 +190,10 @@ module PatchELF
179
190
  end
180
191
  end
181
192
 
193
+ def page_size
194
+ Helper.page_size(@elf.header.e_machine)
195
+ end
196
+
182
197
  def abnormal_elf(msg)
183
198
  raise ArgumentError, msg
184
199
  end
@@ -29,7 +29,7 @@ module PatchELF
29
29
  # :silent = ignore the errors
30
30
  def initialize(filename, on_error: :log, logging: true)
31
31
  @in_file = filename
32
- f = File.open(filename)
32
+ f = File.open(filename) # rubocop:disable Style/FileOpen
33
33
  @elf = ELFTools::ELFFile.new(f)
34
34
  @set = {}
35
35
  @rpath_sym = :runpath
@@ -32,7 +32,7 @@ module PatchELF
32
32
  @set = set
33
33
  # [{Integer => String}]
34
34
  @inline_patch = {}
35
- f = File.open(in_file)
35
+ f = File.open(in_file) # rubocop:disable Style/FileOpen
36
36
  @elf = ELFTools::ELFFile.new(f)
37
37
  @mm = PatchELF::MM.new(@elf)
38
38
  @strtab_extend_requests = []
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PatchELF
4
4
  # Current gem version.
5
- VERSION = '1.5.2'.freeze
5
+ VERSION = '1.6.3'
6
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patchelf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-11-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: elftools
@@ -93,6 +93,20 @@ dependencies:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0.22'
96
+ - !ruby/object:Gem::Dependency
97
+ name: simplecov-cobertura
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '4'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '4'
96
110
  - !ruby/object:Gem::Dependency
97
111
  name: tty-platform
98
112
  requirement: !ruby/object:Gem::Requirement
@@ -144,11 +158,14 @@ files:
144
158
  - lib/patchelf/patcher.rb
145
159
  - lib/patchelf/saver.rb
146
160
  - lib/patchelf/version.rb
147
- homepage: https://github.com/david942j/patchelf.rb
161
+ homepage: https://github.com/Homebrew/patchelf.rb
148
162
  licenses:
149
163
  - MIT
150
164
  metadata:
151
165
  rubygems_mfa_required: 'true'
166
+ source_code_uri: https://github.com/Homebrew/patchelf.rb
167
+ bug_tracker_uri: https://github.com/Homebrew/patchelf.rb/issues
168
+ funding_uri: https://github.com/sponsors/Homebrew
152
169
  rdoc_options: []
153
170
  require_paths:
154
171
  - lib
@@ -156,14 +173,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
173
  requirements:
157
174
  - - ">="
158
175
  - !ruby/object:Gem::Version
159
- version: '3.1'
176
+ version: '3.3'
160
177
  required_rubygems_version: !ruby/object:Gem::Requirement
161
178
  requirements:
162
179
  - - ">="
163
180
  - !ruby/object:Gem::Version
164
181
  version: '0'
165
182
  requirements: []
166
- rubygems_version: 3.6.2
183
+ rubygems_version: 4.0.16
167
184
  specification_version: 4
168
185
  summary: patchelf
169
186
  test_files: []