Module: MachO

Defined in:
lib/macho.rb,
lib/macho/open.rb,
lib/macho/tools.rb,
lib/macho/utils.rb,
lib/macho/headers.rb,
lib/macho/fat_file.rb,
lib/macho/sections.rb,
lib/macho/structure.rb,
lib/macho/exceptions.rb,
lib/macho/macho_file.rb,
lib/macho/load_commands.rb

Overview

The primary namespace for ruby-macho.

Defined Under Namespace

Modules: Tools Classes: CPUSubtypeError, CPUTypeError, DyldInfoCommand, DylibCommand, DylibUnknownError, DylinkerCommand, DysymtabCommand, EncryptionInfoCommand, EncryptionInfoCommand64, EntryPointCommand, FatArch, FatBinaryError, FatFile, FatHeader, FiletypeError, HeaderPadError, LinkeditDataCommand, LinkerOptionCommand, LoadCommand, LoadCommandError, MachHeader, MachHeader64, MachOBinaryError, MachOError, MachOFile, MachOStructure, MagicError, PrebindCksumCommand, PreboundDylibCommand, RoutinesCommand, RoutinesCommand64, RpathCommand, Section, Section64, SegmentCommand, SegmentCommand64, SourceVersionCommand, SubClientCommand, SubFrameworkCommand, SubLibraryCommand, SubUmbrellaCommand, SymtabCommand, ThreadCommand, TwolevelHintsCommand, UUIDCommand, VersionMinCommand

Constant Summary collapse

VERSION =

release version

"0.1.8".freeze
FAT_MAGIC =

big-endian fat magic

0xcafebabe
FAT_CIGAM =

little-endian fat magic

0xbebafeca
MH_MAGIC =

32-bit big-endian magic

0xfeedface
MH_CIGAM =

32-bit little-endian magic

0xcefaedfe
MH_MAGIC_64 =

64-bit big-endian magic

0xfeedfacf
MH_CIGAM_64 =

64-bit little-endian magic

0xcffaedfe
MH_MAGICS =

association of magic numbers to string representations

{
  FAT_MAGIC => "FAT_MAGIC",
  FAT_CIGAM => "FAT_CIGAM",
  MH_MAGIC => "MH_MAGIC",
  MH_CIGAM => "MH_CIGAM",
  MH_MAGIC_64 => "MH_MAGIC_64",
  MH_CIGAM_64 => "MH_CIGAM_64"
}
CPU_ARCH_ABI64 =

mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)

0x01000000
CPU_TYPE_ANY =

any CPU (unused?)

-1
CPU_TYPE_X86 =

x86 compatible CPUs

0x07
CPU_TYPE_I386 =

i386 and later compatible CPUs

CPU_TYPE_X86
CPU_TYPE_X86_64 =

x86_64 (AMD64) compatible CPUs

(CPU_TYPE_X86 | CPU_ARCH_ABI64)
CPU_TYPE_POWERPC =

PowerPC compatible CPUs (7400 series?)

0x24
CPU_TYPE_POWERPC64 =

PowerPC64 compatible CPUs (970 series?)

(CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
CPU_TYPES =

association of cpu types to string representations

{
  CPU_TYPE_ANY => "CPU_TYPE_ANY",
  CPU_TYPE_X86 => "CPU_TYPE_X86",
  CPU_TYPE_I386 => "CPU_TYPE_I386",
  CPU_TYPE_X86_64 => "CPU_TYPE_X86_64",
  CPU_TYPE_POWERPC => "CPU_TYPE_POWERPC",
  CPU_TYPE_POWERPC64 => "CPU_TYPE_POWERPC64"
}
CPU_SUBTYPE_MASK =

mask for CPU subtype capabilities

0xff000000
CPU_SUBTYPE_LIB64 =

64-bit libraries (undocumented!)

0x80000000
CPU_SUBTYPE_X86_ALL =

all x86-type CPUs

3
CPU_SUBTYPE_X86_ARCH1 =

all x86-type CPUs (what makes this different from CPU_SUBTYPE_X86_ALL?)

4
CPU_SUBTYPES =

association of cpu subtypes to string representations

{
  CPU_SUBTYPE_X86_ALL => "CPU_SUBTYPE_X86_ALL",
  CPU_SUBTYPE_X86_ARCH1 => "CPU_SUBTYPE_X86_ARCH1"
}
MH_OBJECT =

relocatable object file

0x1
MH_EXECUTE =

demand paged executable file

0x2
MH_FVMLIB =

fixed VM shared library file

0x3
MH_CORE =

core dump file

0x4
MH_PRELOAD =

preloaded executable file

0x5
MH_DYLIB =

dynamically bound shared library

0x6
MH_DYLINKER =

dynamic link editor

0x7
MH_BUNDLE =

dynamically bound bundle file

0x8
MH_DYLIB_STUB =

shared library stub for static linking only, no section contents

0x9
MH_DSYM =

companion file with only debug sections

0xa
MH_KEXT_BUNDLE =

x86_64 kexts

0xb
MH_FILETYPES =

association of filetypes to string representations

{
  MH_OBJECT => "MH_OBJECT",
  MH_EXECUTE => "MH_EXECUTE",
  MH_FVMLIB => "MH_FVMLIB",
  MH_CORE => "MH_CORE",
  MH_PRELOAD => "MH_PRELOAD",
  MH_DYLIB => "MH_DYLIB",
  MH_DYLINKER => "MH_DYLINKER",
  MH_BUNDLE => "MH_BUNDLE",
  MH_DYLIB_STUB => "MH_DYLIB_STUB",
  MH_DSYM => "MH_DSYM",
  MH_KEXT_BUNDLE => "MH_KEXT_BUNDLE"
}
MH_NOUNDEFS =

the object file has no undefined references (flag)

0x1
0x2
0x4
MH_BINDATLOAD =

the object file's undefined references are bound by the dynamic linker when loaded (flag)

0x8
MH_PREBOUND =

the file has its dynamic undefined references prebound (flag)

0x10
MH_SPLIT_SEGS =

the file has its read-only and read-write segments split (flag)

0x20
MH_LAZY_INIT =

the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) (flag)

0x40
MH_TWOLEVEL =

the image is using two-level name space bindings (flag)

0x80
MH_FORCE_FLAT =

the executable is forcing all images to use flat name space bindings (flag)

0x100
MH_NOMULTIDEFS =

this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used (flag)

0x200
MH_NOPREFIXBINDING =

do not have dyld notify the prebinding agent about this executable (flag)

0x400
MH_PREBINDABLE =

the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set (flag)

0x800
MH_ALLMODSBOUND =

indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set (flag)

0x1000
MH_SUBSECTIONS_VIA_SYMBOLS =

safe to divide up the sections into sub-sections via symbols for dead code stripping (flag)

0x2000
MH_CANONICAL =

the binary has been canonicalized via the unprebind operation (flag)

0x4000
MH_WEAK_DEFINES =

the final linked image contains external weak symbols (flag)

0x8000
MH_BINDS_TO_WEAK =

the final linked image uses weak symbols (flag)

0x10000
MH_ALLOW_STACK_EXECUTION =

When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes (flag)

0x20000
MH_ROOT_SAFE =

When this bit is set, the binary declares it is safe for use in processes with uid zero (flag)

0x40000
MH_SETUID_SAFE =

When this bit is set, the binary declares it is safe for use in processes when issetugid() is true (flag)

0x80000
MH_NO_REEXPORTED_DYLIBS =

When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported (flag)

0x100000
MH_PIE =

When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes (flag)

0x200000
MH_DEAD_STRIPPABLE_DYLIB =

Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib (flag)

0x400000
MH_HAS_TLV_DESCRIPTORS =

Contains a section of type S_THREAD_LOCAL_VARIABLES (flag)

0x800000
MH_NO_HEAP_EXECUTION =

When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes (flag)

0x1000000
MH_APP_EXTENSION_SAFE =

The code was linked for use in an application extension (flag)

0x02000000
MH_FLAGS =

association of mach header flags to string representations

{
  MH_NOUNDEFS => "MH_NOUNDEFS",
  MH_INCRLINK => "MH_INCRLINK",
  MH_DYLDLINK => "MH_DYLDLINK",
  MH_BINDATLOAD => "MH_BINDATLOAD",
  MH_PREBOUND => "MH_PREBOUND",
  MH_SPLIT_SEGS => "MH_SPLIT_SEGS",
  MH_LAZY_INIT => "MH_LAZY_INIT",
  MH_TWOLEVEL => "MH_TWOLEVEL",
  MH_FORCE_FLAT => "MH_FORCE_FLAT",
  MH_NOMULTIDEFS => "MH_NOMULTIDEFS",
  MH_NOPREFIXBINDING => "MH_NOPREFIXBINDING",
  MH_PREBINDABLE => "MH_PREBINDABLE",
  MH_ALLMODSBOUND => "MH_ALLMODSBOUND",
  MH_SUBSECTIONS_VIA_SYMBOLS => "MH_SUBSECTIONS_VIA_SYMBOLS",
  MH_CANONICAL => "MH_CANONICAL",
  MH_WEAK_DEFINES => "MH_WEAK_DEFINES",
  MH_BINDS_TO_WEAK => "MH_BINDS_TO_WEAK",
  MH_ALLOW_STACK_EXECUTION => "MH_ALLOW_STACK_EXECUTION",
  MH_ROOT_SAFE => "MH_ROOT_SAFE",
  MH_SETUID_SAFE => "MH_SETUID_SAFE",
  MH_NO_REEXPORTED_DYLIBS => "MH_NO_REEXPORTED_DYLIBS",
  MH_PIE => "MH_PIE",
  MH_DEAD_STRIPPABLE_DYLIB => "MH_DEAD_STRIPPABLE_DYLIB",
  MH_HAS_TLV_DESCRIPTORS => "MH_HAS_TLV_DESCRIPTORS",
  MH_NO_HEAP_EXECUTION => "MH_NO_HEAP_EXECUTION",
  MH_APP_EXTENSION_SAFE => "MH_APP_EXTENSION_SAFE"
}
SECTION_TYPE =

type mask

0x000000ff
SECTION_ATTRIBUTES =

attributes mask

0xffffff00
SECTION_ATTRIBUTES_USR =

user settable attributes mask

0xff000000
SECTION_ATTRIBUTES_SYS =

system settable attributes mask

0x00ffff00
S_REGULAR =

a regular section

0x0
S_ZEROFILL =

a zero fill on demand section

0x1
S_CSTRING_LITERALS =

a section with only literal C strings

0x2
S_4BYTE_LITERALS =

a section with only 4 byte literals

0x3
S_8BYTE_LITERALS =

a section with only 8 byte literals

0x4
S_LITERAL_POINTERS =

a section with only pointers to literals

0x5
S_NON_LAZY_SYMBOL_POINTERS =

a section with only non-lazy symbol pointers

0x6
S_LAZY_SYMBOL_POINTERS =

a section with only lazy symbol pointers

0x7
S_SYMBOL_STUBS =

a section with only symbol stubs (byte size of stub in reserved2 field)

0x8
S_MOD_INIT_FUNC_POINTERS =

a section with only function pointers for initialization

0x9
S_MOD_TERM_FUNC_POINTERS =

a section with only function pointers for termination

0xa
S_COALESCED =

a section with only symbols that are to be coalesced

0xb
S_GB_ZEROFILE =

a zero fill on demand section that can be larger than 4GB

0xc
S_INTERPOSING =

a section with only pairs of function pointers for interposing

0xd
S_16BYTE_LITERALS =

a section with only 16 byte literals

0xe
S_DTRACE_DOF =

a section containing DTrace Object Format

0xf
S_LAZY_DYLIB_SYMBOL_POINTERS =

a section with only lazy symbol pointers to lazy loaded dylibs

0x10
S_THREAD_LOCAL_REGULAR =

a template of initial values for thread local variables

0x11
S_THREAD_LOCAL_ZEROFILL =

a template of initial values for thread local variables

0x12
S_THREAD_LOCAL_VARIABLES =

thread local variable descriptors

0x13
S_THREAD_LOCAL_VARIABLE_POINTERS =

pointers to thread local variable descriptors

0x14
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS =

functions to call to initialize thread local variable values

0x15
S_ATTR_PURE_INSTRUCTIONS =

a section with only true machine instructions

0x80000000
S_ATTR_NO_TOC =

a section with coalesced symbols that are not to be in a ranlib table of contents

0x40000000
S_ATTR_STRIP_STATIC_SYMS =

static symbols in this section can be stripped in files with the MH_DYLDLINK flag

0x20000000
S_ATTR_NO_DEAD_STRIP =

no dead stripping

0x10000000
S_ATTR_LIVE_SUPPORT =

blocks are live if they reference live blocks

0x08000000
S_ATTR_SELF_MODIFYING_CODE =

used with i386 code stubs written on by dyld

0x04000000
S_ATTR_DEBUG =

a debug section

0x02000000
S_ATTR_SOME_INSTRUCTIONS =

a section containing some machine instructions

0x00000400
S_ATTR_EXT_RELOC =

a section containing external relocation entries

0x00000200
S_ATTR_LOC_RELOC =

a section containing local relocation entries

0x00000100
SECT_TEXT =

currently known section names we don't use these anywhere right now, but they're good to have

"__text"
SECT_FVMLIB_INIT0 =
"__fvmlib_init0"
SECT_FVMLIB_INIT1 =
"__fvmlib_init1"
SECT_DATA =
"__data"
SECT_BSS =
"__bss"
SECT_COMMON =
"__common"
SECT_OBJC_SYMBOLS =
"__symbol_table"
SECT_OBJC_MODULES =
"__module_info"
SECT_OBJC_STRINGS =
"__selector_strs"
SECT_OBJC_REFS =
"__selector_refs"
SECT_ICON_HEADER =
"__header"
SECT_ICON_TIFF =
"__tiff"
LC_REQ_DYLD =

load commands added after OS X 10.1 need to be bitwise ORed with LC_REQ_DYLD to be recognized by the dynamic linder (dyld)

0x80000000
LOAD_COMMANDS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

association of load commands to string representations

{
  0x1 => :LC_SEGMENT,
  0x2 => :LC_SYMTAB,
  0x3 => :LC_SYMSEG,
  0x4 => :LC_THREAD,
  0x5 => :LC_UNIXTHREAD,
  0x6 => :LC_LOADFVMLIB,
  0x7 => :LC_IDFVMLIB,
  0x8 => :LC_IDENT,
  0x9 => :LC_FVMFILE,
  0xa => :LC_PREPAGE,
  0xb => :LC_DYSYMTAB,
  0xc => :LC_LOAD_DYLIB,
  0xd => :LC_ID_DYLIB,
  0xe => :LC_LOAD_DYLINKER,
  0xf => :LC_ID_DYLINKER,
  0x10 => :LC_PREBOUND_DYLIB,
  0x11 => :LC_ROUTINES,
  0x12 => :LC_SUB_FRAMEWORK,
  0x13 => :LC_SUB_UMBRELLA,
  0x14 => :LC_SUB_CLIENT,
  0x15 => :LC_SUB_LIBRARY,
  0x16 => :LC_TWOLEVEL_HINTS,
  0x17 => :LC_PREBIND_CKSUM,
  (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
  0x19 => :LC_SEGMENT_64,
  0x1a => :LC_ROUTINES_64,
  0x1b => :LC_UUID,
  (0x1c | LC_REQ_DYLD) => :LC_RPATH,
  0x1d => :LC_CODE_SIGNATURE,
  0x1e => :LC_SEGMENT_SPLIT_INFO,
  (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
  0x20 => :LC_LAZY_LOAD_DYLIB,
  0x21 => :LC_ENCRYPTION_INFO,
  0x22 => :LC_DYLD_INFO,
  (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
  (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
  0x24 => :LC_VERSION_MIN_MACOSX,
  0x25 => :LC_VERSION_MIN_IPHONEOS,
  0x26 => :LC_FUNCTION_STARTS,
  0x27 => :LC_DYLD_ENVIRONMENT,
  (0x28 | LC_REQ_DYLD) => :LC_MAIN,
  0x29 => :LC_DATA_IN_CODE,
  0x2a => :LC_SOURCE_VERSION,
  0x2b => :LC_DYLIB_CODE_SIGN_DRS,
  0x2c => :LC_ENCRYPTION_INFO_64,
  0x2d => :LC_LINKER_OPTION,
  0x2e => :LC_LINKER_OPTIMIZATION_HINT
}
LC_STRUCTURES =

association of load commands to string representations of class names

{
  :LC_SEGMENT => "SegmentCommand",
  :LC_SYMTAB => "SymtabCommand",
  :LC_SYMSEG => "LoadCommand", # obsolete
  :LC_THREAD => "ThreadCommand",
  :LC_UNIXTHREAD => "ThreadCommand",
  :LC_LOADFVMLIB => "LoadCommand", # obsolete
  :LC_IDFVMLIB => "LoadCommand", # obsolete
  :LC_IDENT => "LoadCommand", # obsolete
  :LC_FVMFILE => "LoadCommand", # reserved for internal use only
  :LC_PREPAGE => "LoadCommand", # reserved for internal use only
  :LC_DYSYMTAB => "DysymtabCommand",
  :LC_LOAD_DYLIB => "DylibCommand",
  :LC_ID_DYLIB => "DylibCommand",
  :LC_LOAD_DYLINKER => "DylinkerCommand",
  :LC_ID_DYLINKER => "DylinkerCommand",
  :LC_PREBOUND_DYLIB => "PreboundDylibCommand",
  :LC_ROUTINES => "RoutinesCommand",
  :LC_SUB_FRAMEWORK => "SubFrameworkCommand",
  :LC_SUB_UMBRELLA => "SubUmbrellaCommand",
  :LC_SUB_CLIENT => "SubClientCommand",
  :LC_SUB_LIBRARY => "SubLibraryCommand",
  :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
  :LC_PREBIND_CKSUM => "PrebindCksumCommand",
  :LC_LOAD_WEAK_DYLIB => "DylibCommand",
  :LC_SEGMENT_64 => "SegmentCommand64",
  :LC_ROUTINES_64 => "RoutinesCommand64",
  :LC_UUID => "UUIDCommand",
  :LC_RPATH => "RpathCommand",
  :LC_CODE_SIGNATURE => "LinkeditDataCommand",
  :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
  :LC_REEXPORT_DYLIB => "DylibCommand",
  :LC_LAZY_LOAD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
  :LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
  :LC_DYLD_INFO => "DyldInfoCommand",
  :LC_DYLD_INFO_ONLY => "DyldInfoCommand",
  :LC_LOAD_UPWARD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
  :LC_VERSION_MIN_MACOSX => "VersionMinCommand",
  :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
  :LC_FUNCTION_STARTS => "LinkeditDataCommand",
  :LC_DYLD_ENVIRONMENT => "DylinkerCommand",
  :LC_MAIN => "EntryPointCommand",
  :LC_DATA_IN_CODE => "LinkeditDataCommand",
  :LC_SOURCE_VERSION => "SourceVersionCommand",
  :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
  :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
  :LC_LINKER_OPTION => "LinkerOptionCommand",
  :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand"
}
SEG_PAGEZERO =

pagezero segment name

"__PAGEZERO"
SEG_TEXT =

text segment name

"__TEXT"
SEG_DATA =

data segment name

"__DATA"
SEG_OBJC =

objective-c runtime segment

"__OBJC"
SEG_ICON =

icon segment

"__ICON"
SEG_LINKEDIT =

link editor structures segment

"__LINKEDIT"
SEG_UNIXSTACK =

unix stack segment

"__UNIXSTACK"
SEG_IMPORT =

segment for self-modifying code with RWX permissions

"__IMPORT"
SG_HIGHVM =

the file contents for this segment is for the high part of the VM space, the low part is zero filled (for stacks in core files)

0x1
SG_FVMLIB =

this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor

0x2
SG_NORELOC =

this segment has nothing that was relocated in it and nothing relocated to it, that is it maybe safely replaced without relocation

0x4
SG_PROTECTED_VERSION_1 =

this segment is protected. if the segment starts at file offset 0, the first page of the segment is not protected. all other pages of the segment are protected.

0x8

Class Method Summary collapse

Class Method Details

.fat_magic?(num) ⇒ Boolean

Returns true if num is a valid Fat magic number, false otherwise.

Parameters:

  • num (Fixnum)

    the number being checked

Returns:

  • (Boolean)

    true if num is a valid Fat magic number, false otherwise



21
22
23
# File 'lib/macho/utils.rb', line 21

def self.fat_magic?(num)
  num == FAT_MAGIC || num == FAT_CIGAM
end

.magic32?(num) ⇒ Boolean

Returns true if num is a valid 32-bit magic number, false otherwise.

Parameters:

  • num (Fixnum)

    the number being checked

Returns:

  • (Boolean)

    true if num is a valid 32-bit magic number, false otherwise



27
28
29
# File 'lib/macho/utils.rb', line 27

def self.magic32?(num)
  num == MH_MAGIC || num == MH_CIGAM
end

.magic64?(num) ⇒ Boolean

Returns true if num is a valid 64-bit magic number, false otherwise.

Parameters:

  • num (Fixnum)

    the number being checked

Returns:

  • (Boolean)

    true if num is a valid 64-bit magic number, false otherwise



33
34
35
# File 'lib/macho/utils.rb', line 33

def self.magic64?(num)
  num == MH_MAGIC_64 || num == MH_CIGAM_64
end

.magic?(num) ⇒ Boolean

Returns true if num is a valid Mach-O magic number, false otherwise.

Parameters:

  • num (Fixnum)

    the number being checked

Returns:

  • (Boolean)

    true if num is a valid Mach-O magic number, false otherwise



15
16
17
# File 'lib/macho/utils.rb', line 15

def self.magic?(num)
  MH_MAGICS.has_key?(num)
end

.open(filename) ⇒ MachO::MachOFile, MachO::FatFile

Opens the given filename as a MachOFile or FatFile, depending on its magic.

Parameters:

  • filename (String)

    the file being opened

Returns:



6
7
8
9
10
11
12
13
14
15
# File 'lib/macho/open.rb', line 6

def self.open(filename)
  # open file and test magic instead of using exceptions for control?
  begin
    file = MachOFile.new(filename)
  rescue FatBinaryError
    file = FatFile.new(filename)
  end

  file
end

.round(value, round) ⇒ Fixnum

Returns the next number >= value such that round is its divisor.

Parameters:

  • value (Fixnum)

    the number being rounded

  • round (Fixnum)

    the number being rounded with

Returns:

  • (Fixnum)

    the next number >= value such that round is its divisor

See Also:



6
7
8
9
10
11
# File 'lib/macho/utils.rb', line 6

def self.round(value, round)
  round -= 1
  value += round
  value &= ~round
  value
end