Merge pull request #494 from sashs/master
Bugfixes and new samples for ruby bindings
This commit is contained in:
commit
56d70845da
106
bindings/ruby/sample_arm.rb
Normal file
106
bindings/ruby/sample_arm.rb
Normal file
@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'unicorn'
|
||||
require 'unicorn/arm_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
# code to be emulated
|
||||
ARM_CODE = "\x37\x00\xa0\xe3\x03\x10\x42\xe0" # mov r0, #0x37; sub r1, r2, r3
|
||||
THUMB_CODE = "\x83\xb0" # sub sp, #0xc
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
$hook_block = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing basic block at 0x%x, block size = 0x%x" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
$hook_code = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing instruction at 0x%x, instruction size = %u" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# Test ARM
|
||||
def test_arm()
|
||||
puts("Emulate ARM code")
|
||||
begin
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc.new UC_ARCH_ARM, UC_MODE_ARM
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, ARM_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM_REG_R0, 0x1234)
|
||||
mu.reg_write(UC_ARM_REG_R2, 0x6789)
|
||||
mu.reg_write(UC_ARM_REG_R3, 0x3333)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + ARM_CODE.bytesize)
|
||||
|
||||
# now print out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r0 = mu.reg_read(UC_ARM_REG_R0)
|
||||
r1 = mu.reg_read(UC_ARM_REG_R1)
|
||||
puts(">>> R0 = 0x%x" % r0)
|
||||
puts(">>> R1 = 0x%x" % r1)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_thumb()
|
||||
puts("Emulate THUMB code")
|
||||
begin
|
||||
# Initialize emulator in thumb mode
|
||||
mu = Uc.new UC_ARCH_ARM, UC_MODE_THUMB
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, THUMB_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM_REG_SP, 0x1234)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + THUMB_CODE.bytesize)
|
||||
|
||||
# now print out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
sp = mu.reg_read(UC_ARM_REG_SP)
|
||||
puts(">>> SP = 0x%x" % sp)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_arm()
|
||||
puts("=" * 20)
|
||||
test_thumb()
|
69
bindings/ruby/sample_arm64.rb
Normal file
69
bindings/ruby/sample_arm64.rb
Normal file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Sample code for ARM64 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Ruby sample ported by Sascha Schirra <sashs82@gmail.com>
|
||||
require 'unicorn'
|
||||
require 'unicorn/arm64_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
# code to be emulated
|
||||
ARM64_CODE = "\xab\x01\x0f\x8b" #add x11, x13, x15
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
$hook_block = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing basic block at 0x%x, block size = 0x%x" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
$hook_code = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing instruction at 0x%x, instruction size = %u" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# Test ARM64
|
||||
def test_arm64()
|
||||
puts("Emulate ARM64 code")
|
||||
begin
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc.new UC_ARCH_ARM64, UC_MODE_ARM
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, ARM64_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM64_REG_X11, 0x1234)
|
||||
mu.reg_write(UC_ARM64_REG_X13, 0x6789)
|
||||
mu.reg_write(UC_ARM64_REG_X15, 0x3333)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + ARM64_CODE.bytesize)
|
||||
|
||||
# now print out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
x11 = mu.reg_read(UC_ARM64_REG_X11)
|
||||
x13 = mu.reg_read(UC_ARM64_REG_X13)
|
||||
x15 = mu.reg_read(UC_ARM64_REG_X15)
|
||||
puts(">>> X11 = 0x%x" % x11)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_arm64()
|
65
bindings/ruby/sample_m68k.rb
Normal file
65
bindings/ruby/sample_m68k.rb
Normal file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Ruby sample ported by Sascha Schirra <sashs82@gmail.com>
|
||||
|
||||
require 'unicorn'
|
||||
require 'unicorn/m68k_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
# code to be emulated
|
||||
M68K_CODE = "\x76\xed" # movq #-19, %d3
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
$hook_block = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing basic block at 0x%x, block size = 0x%x" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
$hook_code = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing instruction at 0x%x, instruction size = %u" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# Test m68k
|
||||
def test_m68k()
|
||||
puts("Emulate M68K code")
|
||||
begin
|
||||
# Initialize emulator in m68k mode
|
||||
mu = Uc.new UC_ARCH_M68K, UC_MODE_BIG_ENDIAN
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, M68K_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_M68K_REG_D3, 0x1234)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + M68K_CODE.bytesize)
|
||||
|
||||
# now print out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
d3 = mu.reg_read(UC_M68K_REG_D3)
|
||||
puts(">>> D3 = 0x%x" % d3)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_m68k()
|
104
bindings/ruby/sample_mips.rb
Normal file
104
bindings/ruby/sample_mips.rb
Normal file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Sample code for MIPS of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Ruby sample ported by Sascha Schirra <sashs82@gmail.com>
|
||||
require 'unicorn'
|
||||
require 'unicorn/mips_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
# code to be emulated
|
||||
MIPS_CODE_EB = "\x34\x21\x34\x56" # ori $at, $at, 0x3456;
|
||||
MIPS_CODE_EL = "\x56\x34\x21\x34" # ori $at, $at, 0x3456;
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
$hook_block = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing basic block at 0x%x, block size = 0x%x" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
$hook_code = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing instruction at 0x%x, instruction size = %u" % [address, size])
|
||||
end
|
||||
|
||||
# Test MIPS EB
|
||||
def test_mips_eb()
|
||||
puts("Emulate MIPS code (big-endian)")
|
||||
begin
|
||||
# Initialize emulator in MIPS32 + EB mode
|
||||
mu = Uc.new UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, MIPS_CODE_EB)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_MIPS_REG_1, 0x6789)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + MIPS_CODE_EB.bytesize)
|
||||
|
||||
# now puts out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r1 = mu.reg_read(UC_MIPS_REG_1)
|
||||
puts(">>> r1 = 0x%x" % r1)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Test MIPS EL
|
||||
def test_mips_el()
|
||||
puts("Emulate MIPS code (little-endian)")
|
||||
begin
|
||||
# Initialize emulator in MIPS32 + EL mode
|
||||
mu = Uc.new UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, MIPS_CODE_EL)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_MIPS_REG_1, 0x6789)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + MIPS_CODE_EL.bytesize)
|
||||
|
||||
# now puts out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r1 = mu.reg_read(UC_MIPS_REG_1)
|
||||
puts(">>> r1 = 0x%x" % r1)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_mips_eb()
|
||||
puts("=" * 20)
|
||||
test_mips_el()
|
65
bindings/ruby/sample_sparc.rb
Normal file
65
bindings/ruby/sample_sparc.rb
Normal file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Sample code for SPARC of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Ruby sample ported by Sascha Schirra <sashs82@gmail.com>
|
||||
require 'unicorn'
|
||||
require 'unicorn/sparc_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
# code to be emulated
|
||||
SPARC_CODE = "\x86\x00\x40\x02" # add %g1, %g2, %g3;
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
$hook_block = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing basic block at 0x%x, block size = 0x%x" % [address, size])
|
||||
end
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
$hook_code = Proc.new do |uc, address, size, user_data|
|
||||
puts(">>> Tracing instruction at 0x%x, instruction size = %u" % [address, size])
|
||||
end
|
||||
|
||||
# Test SPARC
|
||||
def test_sparc()
|
||||
puts("Emulate SPARC code")
|
||||
begin
|
||||
# Initialize emulator in SPARC EB mode
|
||||
mu = Uc.new UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, SPARC_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_SPARC_REG_G1, 0x1230)
|
||||
mu.reg_write(UC_SPARC_REG_G2, 0x6789)
|
||||
mu.reg_write(UC_SPARC_REG_G3, 0x5555)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, $hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, $hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + SPARC_CODE.bytesize)
|
||||
|
||||
# now puts out some registers
|
||||
puts(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
g3 = mu.reg_read(UC_SPARC_REG_G3)
|
||||
puts(">>> G3 = 0x%x" %g3)
|
||||
|
||||
rescue UcError => e
|
||||
puts("ERROR: %s" % e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_sparc()
|
97
bindings/ruby/sample_x86_gdt.rb
Normal file
97
bindings/ruby/sample_x86_gdt.rb
Normal file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env ruby
|
||||
require 'unicorn'
|
||||
require 'unicorn/x86_const'
|
||||
|
||||
include Unicorn
|
||||
|
||||
F_GRANULARITY = 0x8
|
||||
F_PROT_32 = 0x4
|
||||
F_LONG = 0x2
|
||||
F_AVAILABLE = 0x1
|
||||
|
||||
A_PRESENT = 0x80
|
||||
|
||||
A_PRIV_3 = 0x60
|
||||
A_PRIV_2 = 0x40
|
||||
A_PRIV_1 = 0x20
|
||||
A_PRIV_0 = 0x0
|
||||
|
||||
A_CODE = 0x10
|
||||
A_DATA = 0x10
|
||||
A_TSS = 0x0
|
||||
A_GATE = 0x0
|
||||
|
||||
A_DATA_WRITABLE = 0x2
|
||||
A_CODE_READABLE = 0x2
|
||||
|
||||
A_DIR_CON_BIT = 0x4
|
||||
|
||||
S_GDT = 0x0
|
||||
S_LDT = 0x4
|
||||
S_PRIV_3 = 0x3
|
||||
S_PRIV_2 = 0x2
|
||||
S_PRIV_1 = 0x1
|
||||
S_PRIV_0 = 0x0
|
||||
|
||||
def create_selector(idx, flags)
|
||||
to_ret = flags
|
||||
to_ret |= idx << 3
|
||||
return to_ret
|
||||
end
|
||||
|
||||
def create_gdt_entry(base, limit, access, flags)
|
||||
|
||||
to_ret = limit & 0xffff;
|
||||
to_ret |= (base & 0xffffff) << 16;
|
||||
to_ret |= (access & 0xff) << 40;
|
||||
to_ret |= ((limit >> 16) & 0xf) << 48;
|
||||
to_ret |= (flags & 0xff) << 52;
|
||||
to_ret |= ((base >> 24) & 0xff) << 56;
|
||||
return [to_ret].pack('Q')
|
||||
end
|
||||
|
||||
def write_gdt(uc, gdt, mem)
|
||||
gdt.each_index do |idx|
|
||||
offset = idx * GDT_ENTRY_SIZE
|
||||
uc.mem_write(mem + offset, gdt[idx])
|
||||
end
|
||||
end
|
||||
|
||||
CODE_ADDR = 0x40000
|
||||
CODE_SIZE = 0x1000
|
||||
|
||||
GDT_ADDR = 0x3000
|
||||
GDT_LIMIT = 0x1000
|
||||
GDT_ENTRY_SIZE = 0x8
|
||||
|
||||
GS_SEGMENT_ADDR = 0x5000
|
||||
GS_SEGMENT_SIZE = 0x1000
|
||||
|
||||
uc = Uc.new UC_ARCH_X86, UC_MODE_32
|
||||
|
||||
uc.mem_map(GDT_ADDR, GDT_LIMIT)
|
||||
uc.mem_map(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE)
|
||||
uc.mem_map(CODE_ADDR, CODE_SIZE)
|
||||
|
||||
gdt = Array.new (31) {|i| create_gdt_entry(0,0,0,0)}
|
||||
gdt[15] = create_gdt_entry(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE, A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_3 | A_DIR_CON_BIT, F_PROT_32)
|
||||
gdt[16] = create_gdt_entry(0, 0xfffff000 , A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_3 | A_DIR_CON_BIT, F_PROT_32) # Data Segment
|
||||
gdt[17] = create_gdt_entry(0, 0xfffff000 , A_PRESENT | A_CODE | A_CODE_READABLE | A_PRIV_3 | A_DIR_CON_BIT, F_PROT_32) # Code Segment
|
||||
gdt[18] = create_gdt_entry(0, 0xfffff000 , A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_0 | A_DIR_CON_BIT, F_PROT_32) # Stack Segment
|
||||
|
||||
write_gdt(uc, gdt, GDT_ADDR)
|
||||
uc.reg_write(UC_X86_REG_GDTR, [0, GDT_ADDR, gdt.length * GDT_ENTRY_SIZE-1, 0x0])
|
||||
|
||||
selector = create_selector(15, S_GDT | S_PRIV_3)
|
||||
uc.reg_write(UC_X86_REG_GS, selector)
|
||||
|
||||
selector = create_selector(16, S_GDT | S_PRIV_3)
|
||||
uc.reg_write(UC_X86_REG_DS, selector)
|
||||
|
||||
selector = create_selector(17, S_GDT | S_PRIV_3)
|
||||
uc.reg_write(UC_X86_REG_CS, selector)
|
||||
|
||||
selector = create_selector(18, S_GDT | S_PRIV_0)
|
||||
uc.reg_write(UC_X86_REG_SS, selector)
|
||||
|
||||
|
@ -367,7 +367,6 @@ VALUE m_uc_hook_add(int argc, VALUE* argv, VALUE self){
|
||||
err = uc_hook_add(_uc, &trace, htype, cb_hook_insn_syscall,(void *)passthrough, NUM2ULL(begin), NUM2ULL(end), NUM2INT(arg1));
|
||||
break;
|
||||
}
|
||||
err = uc_hook_add(_uc, &trace, htype, cb_hook_intr,(void *)passthrough, NUM2ULL(begin), NUM2ULL(end));
|
||||
}
|
||||
else if(htype == UC_HOOK_INTR){
|
||||
err = uc_hook_add(_uc, &trace, htype, cb_hook_intr,(void *)passthrough, NUM2ULL(begin), NUM2ULL(end));
|
||||
|
2
bindings/ruby/unicorn_gem/pkg/.gitignore
vendored
2
bindings/ruby/unicorn_gem/pkg/.gitignore
vendored
@ -7,4 +7,4 @@
|
||||
/pkg/
|
||||
/spec/reports/
|
||||
/tmp/
|
||||
.gem
|
||||
*.gem
|
||||
|
Binary file not shown.
@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
||||
spec.version = Unicorn::VERSION
|
||||
spec.authors = ["Sascha Schirra"]
|
||||
spec.email = ["sashs@scoding.de"]
|
||||
spec.license = GPLv2
|
||||
spec.license = 'GPL-2.0'
|
||||
spec.summary = %q{Ruby binding for Unicorn-Engine}
|
||||
spec.description = %q{Ruby binding for Unicorn-Engine <unicorn-engine.org>}
|
||||
spec.homepage = "https://unicorn-engine.org"
|
||||
|
Loading…
Reference in New Issue
Block a user