From bc06c1206d770bbc6d5b0b67984a90f5b02c2351 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Fri, 28 Jan 2022 19:55:12 +0100 Subject: macholib, altgraph: update vendored dependency (#28664) --- lib/spack/external/__init__.py | 4 +- lib/spack/external/altgraph/Dot.py | 100 +- lib/spack/external/altgraph/Graph.py | 34 +- lib/spack/external/altgraph/GraphAlgo.py | 53 +- lib/spack/external/altgraph/GraphStat.py | 24 +- lib/spack/external/altgraph/GraphUtil.py | 37 +- lib/spack/external/altgraph/ObjectGraph.py | 12 +- lib/spack/external/altgraph/__init__.py | 14 +- lib/spack/external/macholib/MachO.py | 174 ++- lib/spack/external/macholib/MachOGraph.py | 39 +- lib/spack/external/macholib/MachOStandalone.py | 58 +- lib/spack/external/macholib/SymbolTable.py | 42 +- lib/spack/external/macholib/__init__.py | 2 +- lib/spack/external/macholib/__main__.py | 25 +- lib/spack/external/macholib/_cmdline.py | 15 +- lib/spack/external/macholib/dyld.py | 106 +- lib/spack/external/macholib/dylib.py | 8 +- lib/spack/external/macholib/framework.py | 8 +- lib/spack/external/macholib/itergraphreport.py | 38 +- lib/spack/external/macholib/mach_o.py | 1573 +++++++++++------------ lib/spack/external/macholib/macho_dump.py | 41 +- lib/spack/external/macholib/macho_find.py | 7 +- lib/spack/external/macholib/macho_standalone.py | 13 +- lib/spack/external/macholib/ptypes.py | 103 +- lib/spack/external/macholib/util.py | 68 +- 25 files changed, 1345 insertions(+), 1253 deletions(-) diff --git a/lib/spack/external/__init__.py b/lib/spack/external/__init__.py index 2a00e4fcb2..c0b131807b 100644 --- a/lib/spack/external/__init__.py +++ b/lib/spack/external/__init__.py @@ -11,7 +11,7 @@ altgraph * Homepage: https://altgraph.readthedocs.io/en/latest/index.html * Usage: dependency of macholib -* Version: 0.16.1 +* Version: 0.17.2 archspec -------- @@ -96,7 +96,7 @@ macholib * Homepage: https://macholib.readthedocs.io/en/latest/index.html# * Usage: Manipulation of Mach-o binaries for relocating macOS buildcaches on Linux -* Version: 1.12 +* Version: 1.15.2 markupsafe ---------- diff --git a/lib/spack/external/altgraph/Dot.py b/lib/spack/external/altgraph/Dot.py index 3ef04d4c5b..f265a7121c 100644 --- a/lib/spack/external/altgraph/Dot.py +++ b/lib/spack/external/altgraph/Dot.py @@ -1,4 +1,4 @@ -''' +""" altgraph.Dot - Interface to the dot language ============================================ @@ -107,7 +107,7 @@ Valid attributes - for more details on how to control the graph drawing process see the `graphviz reference `_. -''' +""" import os import warnings @@ -115,25 +115,34 @@ from altgraph import GraphError class Dot(object): - ''' + """ A class providing a **graphviz** (dot language) representation allowing a fine grained control over how the graph is being displayed. If the :command:`dot` and :command:`dotty` programs are not in the current system path their location needs to be specified in the contructor. - ''' + """ def __init__( - self, graph=None, nodes=None, edgefn=None, nodevisitor=None, - edgevisitor=None, name="G", dot='dot', dotty='dotty', - neato='neato', graphtype="digraph"): - ''' + self, + graph=None, + nodes=None, + edgefn=None, + nodevisitor=None, + edgevisitor=None, + name="G", + dot="dot", + dotty="dotty", + neato="neato", + graphtype="digraph", + ): + """ Initialization. - ''' + """ self.name, self.attr = name, {} - assert graphtype in ['graph', 'digraph'] + assert graphtype in ["graph", "digraph"] self.type = graphtype self.temp_dot = "tmp_dot.dot" @@ -148,8 +157,10 @@ class Dot(object): if graph is not None and nodes is None: nodes = graph if graph is not None and edgefn is None: + def edgefn(node, graph=graph): return graph.out_nbrs(node) + if nodes is None: nodes = () @@ -177,20 +188,19 @@ class Dot(object): self.edge_style(head, tail, **edgestyle) def style(self, **attr): - ''' + """ Changes the overall style - ''' + """ self.attr = attr - def display(self, mode='dot'): - ''' + def display(self, mode="dot"): + """ Displays the current graph via dotty - ''' + """ - if mode == 'neato': + if mode == "neato": self.save_dot(self.temp_neo) - neato_cmd = "%s -o %s %s" % ( - self.neato, self.temp_dot, self.temp_neo) + neato_cmd = "%s -o %s %s" % (self.neato, self.temp_dot, self.temp_neo) os.system(neato_cmd) else: self.save_dot(self.temp_dot) @@ -199,24 +209,24 @@ class Dot(object): os.system(plot_cmd) def node_style(self, node, **kwargs): - ''' + """ Modifies a node style to the dot representation. - ''' + """ if node not in self.edges: self.edges[node] = {} self.nodes[node] = kwargs def all_node_style(self, **kwargs): - ''' + """ Modifies all node styles - ''' + """ for node in self.nodes: self.node_style(node, **kwargs) def edge_style(self, head, tail, **kwargs): - ''' + """ Modifies an edge style to the dot representation. - ''' + """ if tail not in self.nodes: raise GraphError("invalid node %s" % (tail,)) @@ -229,10 +239,10 @@ class Dot(object): def iterdot(self): # write graph title - if self.type == 'digraph': - yield 'digraph %s {\n' % (self.name,) - elif self.type == 'graph': - yield 'graph %s {\n' % (self.name,) + if self.type == "digraph": + yield "digraph %s {\n" % (self.name,) + elif self.type == "graph": + yield "graph %s {\n" % (self.name,) else: raise GraphError("unsupported graphtype %s" % (self.type,)) @@ -240,11 +250,11 @@ class Dot(object): # write overall graph attributes for attr_name, attr_value in sorted(self.attr.items()): yield '%s="%s";' % (attr_name, attr_value) - yield '\n' + yield "\n" # some reusable patterns - cpatt = '%s="%s",' # to separate attributes - epatt = '];\n' # to end attributes + cpatt = '%s="%s",' # to separate attributes + epatt = "];\n" # to end attributes # write node attributes for node_name, node_attr in sorted(self.nodes.items()): @@ -256,25 +266,24 @@ class Dot(object): # write edge attributes for head in sorted(self.edges): for tail in sorted(self.edges[head]): - if self.type == 'digraph': + if self.type == "digraph": yield '\t"%s" -> "%s" [' % (head, tail) else: yield '\t"%s" -- "%s" [' % (head, tail) - for attr_name, attr_value in \ - sorted(self.edges[head][tail].items()): + for attr_name, attr_value in sorted(self.edges[head][tail].items()): yield cpatt % (attr_name, attr_value) yield epatt # finish file - yield '}\n' + yield "}\n" def __iter__(self): return self.iterdot() def save_dot(self, file_name=None): - ''' + """ Saves the current graph representation into a file - ''' + """ if not file_name: warnings.warn(DeprecationWarning, "always pass a file_name") @@ -284,19 +293,18 @@ class Dot(object): for chunk in self.iterdot(): fp.write(chunk) - def save_img(self, file_name=None, file_type="gif", mode='dot'): - ''' + def save_img(self, file_name=None, file_type="gif", mode="dot"): + """ Saves the dot file as an image file - ''' + """ if not file_name: warnings.warn(DeprecationWarning, "always pass a file_name") file_name = "out" - if mode == 'neato': + if mode == "neato": self.save_dot(self.temp_neo) - neato_cmd = "%s -o %s %s" % ( - self.neato, self.temp_dot, self.temp_neo) + neato_cmd = "%s -o %s %s" % (self.neato, self.temp_dot, self.temp_neo) os.system(neato_cmd) plot_cmd = self.dot else: @@ -305,5 +313,9 @@ class Dot(object): file_name = "%s.%s" % (file_name, file_type) create_cmd = "%s -T%s %s -o %s" % ( - plot_cmd, file_type, self.temp_dot, file_name) + plot_cmd, + file_type, + self.temp_dot, + file_name, + ) os.system(create_cmd) diff --git a/lib/spack/external/altgraph/Graph.py b/lib/spack/external/altgraph/Graph.py index fc4f7e9743..8088007abd 100644 --- a/lib/spack/external/altgraph/Graph.py +++ b/lib/spack/external/altgraph/Graph.py @@ -13,9 +13,10 @@ altgraph.Graph - Base Graph class #--Nathan Denny, May 27, 1999 """ -from altgraph import GraphError from collections import deque +from altgraph import GraphError + class Graph(object): """ @@ -58,8 +59,10 @@ class Graph(object): raise GraphError("Cannot create edge from %s" % (item,)) def __repr__(self): - return '' % ( - self.number_of_nodes(), self.number_of_edges()) + return "" % ( + self.number_of_nodes(), + self.number_of_edges(), + ) def add_node(self, node, node_data=None): """ @@ -111,7 +114,7 @@ class Graph(object): self.nodes[tail_id][0].append(edge) self.nodes[head_id][1].append(edge) except KeyError: - raise GraphError('Invalid nodes %s -> %s' % (head_id, tail_id)) + raise GraphError("Invalid nodes %s -> %s" % (head_id, tail_id)) # store edge information self.edges[edge] = (head_id, tail_id, edge_data) @@ -124,13 +127,12 @@ class Graph(object): time. """ try: - head_id, tail_id, edge_data = \ - self.hidden_edges[edge] = self.edges[edge] + head_id, tail_id, edge_data = self.hidden_edges[edge] = self.edges[edge] self.nodes[tail_id][0].remove(edge) self.nodes[head_id][1].remove(edge) del self.edges[edge] except KeyError: - raise GraphError('Invalid edge %s' % edge) + raise GraphError("Invalid edge %s" % edge) def hide_node(self, node): """ @@ -144,7 +146,7 @@ class Graph(object): self.hide_edge(edge) del self.nodes[node] except KeyError: - raise GraphError('Invalid node %s' % node) + raise GraphError("Invalid node %s" % node) def restore_node(self, node): """ @@ -157,7 +159,7 @@ class Graph(object): self.restore_edge(edge) del self.hidden_nodes[node] except KeyError: - raise GraphError('Invalid node %s' % node) + raise GraphError("Invalid node %s" % node) def restore_edge(self, edge): """ @@ -170,7 +172,7 @@ class Graph(object): self.edges[edge] = head_id, tail_id, data del self.hidden_edges[edge] except KeyError: - raise GraphError('Invalid edge %s' % edge) + raise GraphError("Invalid edge %s" % edge) def restore_all_edges(self): """ @@ -203,7 +205,7 @@ class Graph(object): head, tail, data = self.edges[edge] except KeyError: head, tail = None, None - raise GraphError('Invalid edge %s' % edge) + raise GraphError("Invalid edge %s" % edge) return (head, tail) @@ -339,7 +341,7 @@ class Graph(object): try: return list(self.nodes[node][1]) except KeyError: - raise GraphError('Invalid node %s' % node) + raise GraphError("Invalid node %s" % node) def inc_edges(self, node): """ @@ -348,7 +350,7 @@ class Graph(object): try: return list(self.nodes[node][0]) except KeyError: - raise GraphError('Invalid node %s' % node) + raise GraphError("Invalid node %s" % node) def all_edges(self, node): """ @@ -488,7 +490,7 @@ class Graph(object): The forward parameter specifies whether it is a forward or backward traversal. """ - visited, stack = set([start]), deque([start]) + visited, stack = {start}, deque([start]) if forward: get_edges = self.out_edges @@ -515,7 +517,7 @@ class Graph(object): condition callback is only called when node_data is not None. """ - visited, stack = set([start]), deque([start]) + visited, stack = {start}, deque([start]) if forward: get_edges = self.out_edges @@ -547,7 +549,7 @@ class Graph(object): traversal. Returns a list of tuples where the first value is the hop value the second value is the node id. """ - queue, visited = deque([(start, 0)]), set([start]) + queue, visited = deque([(start, 0)]), {start} # the direction of the bfs depends on the edges that are sampled if forward: diff --git a/lib/spack/external/altgraph/GraphAlgo.py b/lib/spack/external/altgraph/GraphAlgo.py index b51e536314..f93e73dcda 100644 --- a/lib/spack/external/altgraph/GraphAlgo.py +++ b/lib/spack/external/altgraph/GraphAlgo.py @@ -1,7 +1,7 @@ -''' +""" altgraph.GraphAlgo - Graph algorithms ===================================== -''' +""" from altgraph import GraphError @@ -28,9 +28,9 @@ def dijkstra(graph, start, end=None): Adapted to altgraph by Istvan Albert, Pennsylvania State University - June, 9 2004 """ - D = {} # dictionary of final distances - P = {} # dictionary of predecessors - Q = _priorityDictionary() # estimated distances of non-final vertices + D = {} # dictionary of final distances + P = {} # dictionary of predecessors + Q = _priorityDictionary() # estimated distances of non-final vertices Q[start] = 0 for v in Q: @@ -44,7 +44,8 @@ def dijkstra(graph, start, end=None): if w in D: if vwLength < D[w]: raise GraphError( - "Dijkstra: found better path to already-final vertex") + "Dijkstra: found better path to already-final vertex" + ) elif w not in Q or vwLength < Q[w]: Q[w] = vwLength P[w] = v @@ -76,7 +77,7 @@ def shortest_path(graph, start, end): # Utility classes and functions # class _priorityDictionary(dict): - ''' + """ Priority dictionary using binary heaps (internal use only) David Eppstein, UC Irvine, 8 Mar 2002 @@ -92,22 +93,22 @@ class _priorityDictionary(dict): order. Each item is not removed until the next item is requested, so D[x] will still return a useful value until the next iteration of the for-loop. Each operation takes logarithmic amortized time. - ''' + """ def __init__(self): - ''' + """ Initialize priorityDictionary by creating binary heap of pairs (value,key). Note that changing or removing a dict entry will not remove the old pair from the heap until it is found by smallest() or until the heap is rebuilt. - ''' + """ self.__heap = [] dict.__init__(self) def smallest(self): - ''' + """ Find smallest item after removing deleted items from front of heap. - ''' + """ if len(self) == 0: raise IndexError("smallest of empty priorityDictionary") heap = self.__heap @@ -115,9 +116,11 @@ class _priorityDictionary(dict): lastItem = heap.pop() insertionPoint = 0 while 1: - smallChild = 2*insertionPoint+1 - if smallChild+1 < len(heap) and \ - heap[smallChild] > heap[smallChild+1]: + smallChild = 2 * insertionPoint + 1 + if ( + smallChild + 1 < len(heap) + and heap[smallChild] > heap[smallChild + 1] + ): smallChild += 1 if smallChild >= len(heap) or lastItem <= heap[smallChild]: heap[insertionPoint] = lastItem @@ -127,22 +130,24 @@ class _priorityDictionary(dict): return heap[0][1] def __iter__(self): - ''' + """ Create destructive sorted iterator of priorityDictionary. - ''' + """ + def iterfn(): while len(self) > 0: x = self.smallest() yield x del self[x] + return iterfn() def __setitem__(self, key, val): - ''' + """ Change value stored in dictionary and add corresponding pair to heap. Rebuilds the heap if the number of deleted items gets large, to avoid memory leakage. - ''' + """ dict.__setitem__(self, key, val) heap = self.__heap if len(heap) > 2 * len(self): @@ -152,15 +157,15 @@ class _priorityDictionary(dict): newPair = (val, key) insertionPoint = len(heap) heap.append(None) - while insertionPoint > 0 and newPair < heap[(insertionPoint-1)//2]: - heap[insertionPoint] = heap[(insertionPoint-1)//2] - insertionPoint = (insertionPoint-1)//2 + while insertionPoint > 0 and newPair < heap[(insertionPoint - 1) // 2]: + heap[insertionPoint] = heap[(insertionPoint - 1) // 2] + insertionPoint = (insertionPoint - 1) // 2 heap[insertionPoint] = newPair def setdefault(self, key, val): - ''' + """ Reimplement setdefault to pass through our customized __setitem__. - ''' + """ if key not in self: self[key] = val return self[key] diff --git a/lib/spack/external/altgraph/GraphStat.py b/lib/spack/external/altgraph/GraphStat.py index 003b7167e7..577464b41e 100644 --- a/lib/spack/external/altgraph/GraphStat.py +++ b/lib/spack/external/altgraph/GraphStat.py @@ -1,11 +1,11 @@ -''' +""" altgraph.GraphStat - Functions providing various graph statistics ================================================================= -''' +""" -def degree_dist(graph, limits=(0, 0), bin_num=10, mode='out'): - ''' +def degree_dist(graph, limits=(0, 0), bin_num=10, mode="out"): + """ Computes the degree distribution for a graph. Returns a list of tuples where the first element of the tuple is the @@ -15,10 +15,10 @@ def degree_dist(graph, limits=(0, 0), bin_num=10, mode='out'): Example:: .... - ''' + """ deg = [] - if mode == 'inc': + if mode == "inc": get_deg = graph.inc_degree else: get_deg = graph.out_degree @@ -34,38 +34,38 @@ def degree_dist(graph, limits=(0, 0), bin_num=10, mode='out'): return results -_EPS = 1.0/(2.0**32) +_EPS = 1.0 / (2.0 ** 32) def _binning(values, limits=(0, 0), bin_num=10): - ''' + """ Bins data that falls between certain limits, if the limits are (0, 0) the minimum and maximum values are used. Returns a list of tuples where the first element of the tuple is the center of the bin and the second element of the tuple are the counts. - ''' + """ if limits == (0, 0): min_val, max_val = min(values) - _EPS, max(values) + _EPS else: min_val, max_val = limits # get bin size - bin_size = (max_val - min_val)/float(bin_num) + bin_size = (max_val - min_val) / float(bin_num) bins = [0] * (bin_num) # will ignore these outliers for now for value in values: try: if (value - min_val) >= 0: - index = int((value - min_val)/float(bin_size)) + index = int((value - min_val) / float(bin_size)) bins[index] += 1 except IndexError: pass # make it ready for an x,y plot result = [] - center = (bin_size/2) + min_val + center = (bin_size / 2) + min_val for i, y in enumerate(bins): x = center + bin_size * i result.append((x, y)) diff --git a/lib/spack/external/altgraph/GraphUtil.py b/lib/spack/external/altgraph/GraphUtil.py index 500a74b9f7..cfd6a34f3c 100644 --- a/lib/spack/external/altgraph/GraphUtil.py +++ b/lib/spack/external/altgraph/GraphUtil.py @@ -1,31 +1,29 @@ -''' +""" altgraph.GraphUtil - Utility classes and functions ================================================== -''' +""" import random from collections import deque -from altgraph import Graph -from altgraph import GraphError +from altgraph import Graph, GraphError -def generate_random_graph( - node_num, edge_num, self_loops=False, multi_edges=False): - ''' + +def generate_random_graph(node_num, edge_num, self_loops=False, multi_edges=False): + """ Generates and returns a :py:class:`~altgraph.Graph.Graph` instance with *node_num* nodes randomly connected by *edge_num* edges. - ''' + """ g = Graph.Graph() if not multi_edges: if self_loops: max_edges = node_num * node_num else: - max_edges = node_num * (node_num-1) + max_edges = node_num * (node_num - 1) if edge_num > max_edges: - raise GraphError( - "inconsistent arguments to 'generate_random_graph'") + raise GraphError("inconsistent arguments to 'generate_random_graph'") nodes = range(node_num) @@ -52,17 +50,16 @@ def generate_random_graph( return g -def generate_scale_free_graph( - steps, growth_num, self_loops=False, multi_edges=False): - ''' +def generate_scale_free_graph(steps, growth_num, self_loops=False, multi_edges=False): + """ Generates and returns a :py:class:`~altgraph.Graph.Graph` instance that - will have *steps* \* *growth_num* nodes and a scale free (powerlaw) + will have *steps* \\* *growth_num* nodes and a scale free (powerlaw) connectivity. Starting with a fully connected graph with *growth_num* nodes at every step *growth_num* nodes are added to the graph and are connected to existing nodes with a probability proportional to the degree of these existing nodes. - ''' - # FIXME: The code doesn't seem to do what the documentation claims. + """ + # The code doesn't seem to do what the documentation claims. graph = Graph.Graph() # initialize the graph @@ -113,7 +110,7 @@ def filter_stack(graph, head, filters): in *removes*. """ - visited, removes, orphans = set([head]), set(), set() + visited, removes, orphans = {head}, set(), set() stack = deque([(head, head)]) get_data = graph.node_data get_edges = graph.out_edges @@ -137,8 +134,6 @@ def filter_stack(graph, head, filters): visited.add(tail) stack.append((last_good, tail)) - orphans = [ - (lg, tl) - for (lg, tl) in orphans if tl not in removes] + orphans = [(lg, tl) for (lg, tl) in orphans if tl not in removes] return visited, removes, orphans diff --git a/lib/spack/external/altgraph/ObjectGraph.py b/lib/spack/external/altgraph/ObjectGraph.py index f3d6fa187b..379b05b129 100644 --- a/lib/spack/external/altgraph/ObjectGraph.py +++ b/lib/spack/external/altgraph/ObjectGraph.py @@ -27,7 +27,7 @@ class ObjectGraph(object): graph.add_node(self, None) def __repr__(self): - return '<%s>' % (type(self).__name__,) + return "<%s>" % (type(self).__name__,) def flatten(self, condition=None, start=None): """ @@ -58,6 +58,7 @@ class ObjectGraph(object): if ident not in seen: yield self.findNode(ident) seen.add(ident) + return iter_edges(outraw, 3), iter_edges(incraw, 2) def edgeData(self, fromNode, toNode): @@ -87,12 +88,12 @@ class ObjectGraph(object): visited, removes, orphans = filter_stack(self.graph, self, filters) for last_good, tail in orphans: - self.graph.add_edge(last_good, tail, edge_data='orphan') + self.graph.add_edge(last_good, tail, edge_data="orphan") for node in removes: self.graph.hide_node(node) - return len(visited)-1, len(removes), len(orphans) + return len(visited) - 1, len(removes), len(orphans) def removeNode(self, node): """ @@ -135,7 +136,7 @@ class ObjectGraph(object): """ if node is self: return node - ident = getattr(node, 'graphident', None) + ident = getattr(node, "graphident", None) return ident def __contains__(self, node): @@ -192,8 +193,7 @@ class ObjectGraph(object): Print a debug message with the given level """ if s and level <= self.debug: - print("%s%s %s" % ( - " " * self.indent, s, ' '.join(map(repr, args)))) + print("%s%s %s" % (" " * self.indent, s, " ".join(map(repr, args)))) def msgin(self, level, s, *args): """ diff --git a/lib/spack/external/altgraph/__init__.py b/lib/spack/external/altgraph/__init__.py index ee70a9c91b..a56342438b 100644 --- a/lib/spack/external/altgraph/__init__.py +++ b/lib/spack/external/altgraph/__init__.py @@ -1,4 +1,4 @@ -''' +""" altgraph - a python graph library ================================= @@ -138,13 +138,11 @@ To display the graph we can use the GraphViz backend:: @newfield contributor: Contributors: @contributor: U{Reka Albert } -''' -# import pkg_resources -# __version__ = pkg_resources.require('altgraph')[0].version -# pkg_resources is not finding the altgraph import despite the fact that it is in sys.path -# there is no .dist-info or .egg-info for pkg_resources to query the version from -# so it must be set manually -__version__ = '0.16.1' +""" +import pkg_resources + +__version__ = pkg_resources.require("altgraph")[0].version + class GraphError(ValueError): pass diff --git a/lib/spack/external/macholib/MachO.py b/lib/spack/external/macholib/MachO.py index 84b4e4b717..3db95201f0 100644 --- a/lib/spack/external/macholib/MachO.py +++ b/lib/spack/external/macholib/MachO.py @@ -3,21 +3,43 @@ Utilities for reading and writing Mach-O headers """ from __future__ import print_function -import sys -import struct import os +import struct +import sys + +from macholib.util import fileview -from .mach_o import MH_FILETYPE_SHORTNAMES, LC_DYSYMTAB, LC_SYMTAB -from .mach_o import load_command, S_ZEROFILL, section_64, section -from .mach_o import LC_REGISTRY, LC_ID_DYLIB, LC_SEGMENT, fat_header -from .mach_o import LC_SEGMENT_64, MH_CIGAM_64, MH_MAGIC_64, FAT_MAGIC -from .mach_o import mach_header, fat_arch64, FAT_MAGIC_64, fat_arch -from .mach_o import LC_REEXPORT_DYLIB, LC_PREBOUND_DYLIB, LC_LOAD_WEAK_DYLIB -from .mach_o import LC_LOAD_UPWARD_DYLIB, LC_LOAD_DYLIB, mach_header_64 -from .mach_o import MH_CIGAM, MH_MAGIC +from .mach_o import ( + FAT_MAGIC, + FAT_MAGIC_64, + LC_DYSYMTAB, + LC_ID_DYLIB, + LC_LOAD_DYLIB, + LC_LOAD_UPWARD_DYLIB, + LC_LOAD_WEAK_DYLIB, + LC_PREBOUND_DYLIB, + LC_REEXPORT_DYLIB, + LC_REGISTRY, + LC_SEGMENT, + LC_SEGMENT_64, + LC_SYMTAB, + MH_CIGAM, + MH_CIGAM_64, + MH_FILETYPE_SHORTNAMES, + MH_MAGIC, + MH_MAGIC_64, + S_ZEROFILL, + fat_arch, + fat_arch64, + fat_header, + load_command, + mach_header, + mach_header_64, + section, + section_64, +) from .ptypes import sizeof -from macholib.util import fileview try: from macholib.compat import bytes except ImportError: @@ -31,23 +53,23 @@ except NameError: if sys.version_info[0] == 2: range = xrange # noqa: F821 -__all__ = ['MachO'] +__all__ = ["MachO"] -_RELOCATABLE = set(( +_RELOCATABLE = { # relocatable commands that should be used for dependency walking LC_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_PREBOUND_DYLIB, LC_REEXPORT_DYLIB, -)) +} _RELOCATABLE_NAMES = { - LC_LOAD_DYLIB: 'load_dylib', - LC_LOAD_UPWARD_DYLIB: 'load_upward_dylib', - LC_LOAD_WEAK_DYLIB: 'load_weak_dylib', - LC_PREBOUND_DYLIB: 'prebound_dylib', - LC_REEXPORT_DYLIB: 'reexport_dylib', + LC_LOAD_DYLIB: "load_dylib", + LC_LOAD_UPWARD_DYLIB: "load_upward_dylib", + LC_LOAD_WEAK_DYLIB: "load_weak_dylib", + LC_PREBOUND_DYLIB: "prebound_dylib", + LC_REEXPORT_DYLIB: "reexport_dylib", } @@ -65,13 +87,14 @@ def lc_str_value(offset, cmd_info): cmd_load, cmd_cmd, cmd_data = cmd_info offset -= sizeof(cmd_load) + sizeof(cmd_cmd) - return cmd_data[offset:].strip(b'\x00') + return cmd_data[offset:].strip(b"\x00") class MachO(object): """ Provides reading/writing the Mach-O header of a specific existing file """ + # filename - the original filename of this mach-o # sizediff - the current deviation from the initial mach-o size # header - the mach-o header @@ -91,7 +114,7 @@ class MachO(object): # initialized by load self.fat = None self.headers = [] - with open(filename, 'rb') as fp: + with open(filename, "rb") as fp: self.load(fp) def __repr__(self): @@ -99,7 +122,7 @@ class MachO(object): def load(self, fh): assert fh.tell() == 0 - header = struct.unpack('>I', fh.read(4))[0] + header = struct.unpack(">I", fh.read(4))[0] fh.seek(0) if header in (FAT_MAGIC, FAT_MAGIC_64): self.load_fat(fh) @@ -112,11 +135,9 @@ class MachO(object): def load_fat(self, fh): self.fat = fat_header.from_fileobj(fh) if self.fat.magic == FAT_MAGIC: - archs = [fat_arch.from_fileobj(fh) - for i in range(self.fat.nfat_arch)] + archs = [fat_arch.from_fileobj(fh) for i in range(self.fat.nfat_arch)] elif self.fat.magic == FAT_MAGIC_64: - archs = [fat_arch64.from_fileobj(fh) - for i in range(self.fat.nfat_arch)] + archs = [fat_arch64.from_fileobj(fh) for i in range(self.fat.nfat_arch)] else: raise ValueError("Unknown fat header magic: %r" % (self.fat.magic)) @@ -132,19 +153,18 @@ class MachO(object): def load_header(self, fh, offset, size): fh.seek(offset) - header = struct.unpack('>I', fh.read(4))[0] + header = struct.unpack(">I", fh.read(4))[0] fh.seek(offset) if header == MH_MAGIC: - magic, hdr, endian = MH_MAGIC, mach_header, '>' + magic, hdr, endian = MH_MAGIC, mach_header, ">" elif header == MH_CIGAM: - magic, hdr, endian = MH_CIGAM, mach_header, '<' + magic, hdr, endian = MH_CIGAM, mach_header, "<" elif header == MH_MAGIC_64: - magic, hdr, endian = MH_MAGIC_64, mach_header_64, '>' + magic, hdr, endian = MH_MAGIC_64, mach_header_64, ">" elif header == MH_CIGAM_64: - magic, hdr, endian = MH_CIGAM_64, mach_header_64, '<' + magic, hdr, endian = MH_CIGAM_64, mach_header_64, "<" else: - raise ValueError("Unknown Mach-O header: 0x%08x in %r" % ( - header, fh)) + raise ValueError("Unknown Mach-O header: 0x%08x in %r" % (header, fh)) hdr = MachOHeader(self, fh, offset, size, magic, hdr, endian) self.headers.append(hdr) @@ -157,6 +177,7 @@ class MachOHeader(object): """ Provides reading/writing the Mach-O header of a specific existing file """ + # filename - the original filename of this mach-o # sizediff - the current deviation from the initial mach-o size # header - the mach-o header @@ -189,15 +210,19 @@ class MachOHeader(object): def __repr__(self): return "<%s filename=%r offset=%d size=%d endian=%r>" % ( - type(self).__name__, self.parent.filename, self.offset, self.size, - self.endian) + type(self).__name__, + self.parent.filename, + self.offset, + self.size, + self.endian, + ) def load(self, fh): fh = fileview(fh, self.offset, self.size) fh.seek(0) self.sizediff = 0 - kw = {'_endian_': self.endian} + kw = {"_endian_": self.endian} header = self.mach_header.from_fileobj(fh, **kw) self.header = header # if header.magic != self.MH_MAGIC: @@ -236,8 +261,9 @@ class MachOHeader(object): section_cls = section_64 expected_size = ( - sizeof(klass) + sizeof(load_command) + - (sizeof(section_cls) * cmd_cmd.nsects) + sizeof(klass) + + sizeof(load_command) + + (sizeof(section_cls) * cmd_cmd.nsects) ) if cmd_load.cmdsize != expected_size: raise ValueError("Segment size mismatch") @@ -248,12 +274,12 @@ class MachOHeader(object): low_offset = min(low_offset, cmd_cmd.fileoff) else: # this one has multiple segments - for j in range(cmd_cmd.nsects): + for _j in range(cmd_cmd.nsects): # read the segment seg = section_cls.from_fileobj(fh, **kw) # if the segment has a size and is not zero filled # then its beginning is the offset of this segment - not_zerofill = ((seg.flags & S_ZEROFILL) != S_ZEROFILL) + not_zerofill = (seg.flags & S_ZEROFILL) != S_ZEROFILL if seg.offset > 0 and seg.size > 0 and not_zerofill: low_offset = min(low_offset, seg.offset) if not_zerofill: @@ -266,7 +292,7 @@ class MachOHeader(object): # data is a list of segments cmd_data = segs - # XXX: Disabled for now because writing back doesn't work + # These are disabled for now because writing back doesn't work # elif cmd_load.cmd == LC_CODE_SIGNATURE: # c = fh.tell() # fh.seek(cmd_cmd.dataoff) @@ -280,17 +306,17 @@ class MachOHeader(object): else: # data is a raw str - data_size = ( - cmd_load.cmdsize - sizeof(klass) - sizeof(load_command) - ) + data_size = cmd_load.cmdsize - sizeof(klass) - sizeof(load_command) cmd_data = fh.read(data_size) cmd.append((cmd_load, cmd_cmd, cmd_data)) read_bytes += cmd_load.cmdsize # make sure the header made sense if read_bytes != header.sizeofcmds: - raise ValueError("Read %d bytes, header reports %d bytes" % ( - read_bytes, header.sizeofcmds)) + raise ValueError( + "Read %d bytes, header reports %d bytes" + % (read_bytes, header.sizeofcmds) + ) self.total_size = sizeof(self.mach_header) + read_bytes self.low_offset = low_offset @@ -303,8 +329,9 @@ class MachOHeader(object): if shouldRelocateCommand(lc.cmd): name = _RELOCATABLE_NAMES[lc.cmd] ofs = cmd.name - sizeof(lc.__class__) - sizeof(cmd.__class__) - yield idx, name, data[ofs:data.find(b'\x00', ofs)].decode( - sys.getfilesystemencoding()) + yield idx, name, data[ + ofs : data.find(b"\x00", ofs) # noqa: E203 + ].decode(sys.getfilesystemencoding()) def rewriteInstallNameCommand(self, loadcmd): """Rewrite the load command of this dylib""" @@ -317,8 +344,9 @@ class MachOHeader(object): self.sizediff += bytes if (self.total_size + self.sizediff) > self.low_offset: print( - "WARNING: Mach-O header in %r may be too large to relocate" % ( - self.parent.filename,)) + "WARNING: Mach-O header in %r may be too large to relocate" + % (self.parent.filename,) + ) def rewriteLoadCommands(self, changefunc): """ @@ -327,22 +355,22 @@ class MachOHeader(object): data = changefunc(self.parent.filename) changed = False if data is not None: - if self.rewriteInstallNameCommand( - data.encode(sys.getfilesystemencoding())): + if self.rewriteInstallNameCommand(data.encode(sys.getfilesystemencoding())): changed = True - for idx, name, filename in self.walkRelocatables(): + for idx, _name, filename in self.walkRelocatables(): data = changefunc(filename) if data is not None: - if self.rewriteDataForCommand(idx, data.encode( - sys.getfilesystemencoding())): + if self.rewriteDataForCommand( + idx, data.encode(sys.getfilesystemencoding()) + ): changed = True return changed def rewriteDataForCommand(self, idx, data): lc, cmd, old_data = self.commands[idx] hdrsize = sizeof(lc.__class__) + sizeof(cmd.__class__) - align = struct.calcsize('Q') - data = data + (b'\x00' * (align - (len(data) % align))) + align = struct.calcsize("Q") + data = data + (b"\x00" * (align - (len(data) % align))) newsize = hdrsize + len(data) self.commands[idx] = (lc, cmd, data) self.changedHeaderSizeBy(newsize - lc.cmdsize) @@ -352,10 +380,17 @@ class MachOHeader(object): def synchronize_size(self): if (self.total_size + self.sizediff) > self.low_offset: raise ValueError( - ("New Mach-O header is too large to relocate in %r " - "(new size=%r, max size=%r, delta=%r)") % ( - self.parent.filename, self.total_size + self.sizediff, - self.low_offset, self.sizediff)) + ( + "New Mach-O header is too large to relocate in %r " + "(new size=%r, max size=%r, delta=%r)" + ) + % ( + self.parent.filename, + self.total_size + self.sizediff, + self.low_offset, + self.sizediff, + ) + ) self.header.sizeofcmds += self.sizediff self.total_size = sizeof(self.mach_header) + self.header.sizeofcmds self.sizediff = 0 @@ -396,16 +431,16 @@ class MachOHeader(object): # zero out the unused space, doubt this is strictly necessary # and is generally probably already the case - fileobj.write(b'\x00' * (self.low_offset - fileobj.tell())) + fileobj.write(b"\x00" * (self.low_offset - fileobj.tell())) def getSymbolTableCommand(self): - for lc, cmd, data in self.commands: + for lc, cmd, _data in self.commands: if lc.cmd == LC_SYMTAB: return cmd return None def getDynamicSymbolTableCommand(self): - for lc, cmd, data in self.commands: + for lc, cmd, _data in self.commands: if lc.cmd == LC_DYSYMTAB: return cmd return None @@ -414,22 +449,23 @@ class MachOHeader(object): if filetype in MH_FILETYPE_SHORTNAMES: return MH_FILETYPE_SHORTNAMES[filetype] else: - return 'unknown' + return "unknown" def main(fn): m = MachO(fn) seen = set() for header in m.headers: - for idx, name, other in header.walkRelocatables(): + for _idx, name, other in header.walkRelocatables(): if other not in seen: seen.add(other) - print('\t' + name + ": " + other) + print("\t" + name + ": " + other) -if __name__ == '__main__': +if __name__ == "__main__": import sys - files = sys.argv[1:] or ['/bin/ls'] + + files = sys.argv[1:] or ["/bin/ls"] for fn in files: print(fn) main(fn) diff --git a/lib/spack/external/macholib/MachOGraph.py b/lib/spack/external/macholib/MachOGraph.py index 5a733c3ed0..8943ed8bd3 100644 --- a/lib/spack/external/macholib/MachOGraph.py +++ b/lib/spack/external/macholib/MachOGraph.py @@ -8,10 +8,10 @@ import sys from altgraph.ObjectGraph import ObjectGraph from macholib.dyld import dyld_find -from macholib.MachO import MachO from macholib.itergraphreport import itergraphreport +from macholib.MachO import MachO -__all__ = ['MachOGraph'] +__all__ = ["MachOGraph"] try: unicode @@ -25,13 +25,14 @@ class MissingMachO(object): self.headers = () def __repr__(self): - return '<%s graphident=%r>' % (type(self).__name__, self.graphident) + return "<%s graphident=%r>" % (type(self).__name__, self.graphident) class MachOGraph(ObjectGraph): """ Graph data structure of Mach-O dependencies """ + def __init__(self, debug=0, graph=None, env=None, executable_path=None): super(MachOGraph, self).__init__(debug=debug, graph=graph) self.env = env @@ -41,16 +42,18 @@ class MachOGraph(ObjectGraph): def locate(self, filename, loader=None): if not isinstance(filename, (str, unicode)): raise TypeError("%r is not a string" % (filename,)) - if filename.startswith('@loader_path/') and loader is not None: + if filename.startswith("@loader_path/") and loader is not None: fn = self.trans_table.get((loader.filename, filename)) if fn is None: loader_path = loader.loader_path try: fn = dyld_find( - filename, env=self.env, + filename, + env=self.env, executable_path=self.executable_path, - loader_path=loader_path) + loader_path=loader_path, + ) self.trans_table[(loader.filename, filename)] = fn except ValueError: return None @@ -60,8 +63,8 @@ class MachOGraph(ObjectGraph): if fn is None: try: fn = dyld_find( - filename, env=self.env, - executable_path=self.executable_path) + filename, env=self.env, executable_path=self.executable_path + ) self.trans_table[filename] = fn except ValueError: return None @@ -83,11 +86,11 @@ class MachOGraph(ObjectGraph): m = self.findNode(pathname, loader=caller) if m is None: if not os.path.exists(pathname): - raise ValueError('%r does not exist' % (pathname,)) + raise ValueError("%r does not exist" % (pathname,)) m = self.createNode(MachO, pathname) - self.createReference(caller, m, edge_data='run_file') + self.createReference(caller, m, edge_data="run_file") self.scan_node(m) - self.msgout(2, '') + self.msgout(2, "") return m def load_file(self, name, caller=None): @@ -103,20 +106,20 @@ class MachOGraph(ObjectGraph): self.scan_node(m) else: m = self.createNode(MissingMachO, name) - self.msgout(2, '') + self.msgout(2, "") return m def scan_node(self, node): - self.msgin(2, 'scan_node', node) + self.msgin(2, "scan_node", node) for header in node.headers: - for idx, name, filename in header.walkRelocatables(): + for _idx, name, filename in header.walkRelocatables(): assert isinstance(name, (str, unicode)) assert isinstance(filename, (str, unicode)) m = self.load_file(filename, caller=node) self.createReference(node, m, edge_data=name) - self.msgout(2, '', node) + self.msgout(2, "", node) - def itergraphreport(self, name='G'): + def itergraphreport(self, name="G"): nodes = map(self.graph.describe_node, self.graph.iterdfs(self)) describe_edge = self.graph.describe_edge return itergraphreport(nodes, describe_edge, name=name) @@ -134,5 +137,5 @@ def main(args): g.graphreport() -if __name__ == '__main__': - main(sys.argv[1:] or ['/bin/ls']) +if __name__ == "__main__": + main(sys.argv[1:] or ["/bin/ls"]) diff --git a/lib/spack/external/macholib/MachOStandalone.py b/lib/spack/external/macholib/MachOStandalone.py index c4f5b84d19..6ce154227c 100644 --- a/lib/spack/external/macholib/MachOStandalone.py +++ b/lib/spack/external/macholib/MachOStandalone.py @@ -1,10 +1,16 @@ import os +from collections import deque -from macholib.MachOGraph import MachOGraph, MissingMachO -from macholib.util import iter_platform_files, in_system_path, mergecopy, \ - mergetree, flipwritable, has_filename_filter from macholib.dyld import framework_info -from collections import deque +from macholib.MachOGraph import MachOGraph, MissingMachO +from macholib.util import ( + flipwritable, + has_filename_filter, + in_system_path, + iter_platform_files, + mergecopy, + mergetree, +) class ExcludedMachO(MissingMachO): @@ -23,22 +29,20 @@ class FilteredMachOGraph(MachOGraph): def locate(self, filename, loader=None): newname = super(FilteredMachOGraph, self).locate(filename, loader) - print("locate", filename, loader, "->", newname) if newname is None: return None return self.delegate.locate(newname, loader=loader) class MachOStandalone(object): - def __init__( - self, base, dest=None, graph=None, env=None, - executable_path=None): - self.base = os.path.join(os.path.abspath(base), '') + def __init__(self, base, dest=None, graph=None, env=None, executable_path=None): + self.base = os.path.join(os.path.abspath(base), "") if dest is None: - dest = os.path.join(self.base, 'Contents', 'Frameworks') + dest = os.path.join(self.base, "Contents", "Frameworks") self.dest = dest self.mm = FilteredMachOGraph( - self, graph=graph, env=env, executable_path=executable_path) + self, graph=graph, env=env, executable_path=executable_path + ) self.changemap = {} self.excludes = [] self.pending = deque() @@ -80,8 +84,7 @@ class MachOStandalone(object): # when two libraries link to the same dylib but using different # symlinks. if os.path.islink(filename): - dest = os.path.join( - self.dest, os.path.basename(os.path.realpath(filename))) + dest = os.path.join(self.dest, os.path.basename(os.path.realpath(filename))) else: dest = os.path.join(self.dest, os.path.basename(filename)) @@ -96,9 +99,9 @@ class MachOStandalone(object): return mergetree(src, dest) def copy_framework(self, info): - dest = os.path.join(self.dest, info['shortname'] + '.framework') - destfn = os.path.join(self.dest, info['name']) - src = os.path.join(info['location'], info['shortname'] + '.framework') + dest = os.path.join(self.dest, info["shortname"] + ".framework") + destfn = os.path.join(self.dest, info["name"]) + src = os.path.join(info["location"], info["shortname"] + ".framework") if not os.path.exists(dest): self.mergetree(src, dest) self.pending.append((destfn, iter_platform_files(dest))) @@ -107,7 +110,7 @@ class MachOStandalone(object): def run(self, platfiles=None, contents=None): mm = self.mm if contents is None: - contents = '@executable_path/..' + contents = "@executable_path/.." if platfiles is None: platfiles = iter_platform_files(self.base) @@ -121,18 +124,20 @@ class MachOStandalone(object): mm.run_file(fn, caller=ref) changemap = {} - skipcontents = os.path.join(os.path.dirname(self.dest), '') + skipcontents = os.path.join(os.path.dirname(self.dest), "") machfiles = [] for node in mm.flatten(has_filename_filter): machfiles.append(node) dest = os.path.join( - contents, os.path.normpath(node.filename[len(skipcontents):])) + contents, + os.path.normpath(node.filename[len(skipcontents) :]), # noqa: E203 + ) changemap[node.filename] = dest def changefunc(path): - if path.startswith('@loader_path/'): - # XXX: This is a quick hack for py2app: In that + if path.startswith("@loader_path/"): + # This is a quick hack for py2app: In that # usecase paths like this are found in the load # commands of relocatable wheels. Those don't # need rewriting. @@ -140,9 +145,8 @@ class MachOStandalone(object): res = mm.locate(path) rv = changemap.get(res) - if rv is None and path.startswith('@loader_path/'): - rv = changemap.get(mm.locate(mm.trans_table.get( - (node.filename, path)))) + if rv is None and path.startswith("@loader_path/"): + rv = changemap.get(mm.locate(mm.trans_table.get((node.filename, path)))) return rv for node in machfiles: @@ -150,14 +154,14 @@ class MachOStandalone(object): if fn is None: continue rewroteAny = False - for header in node.headers: + for _header in node.headers: if node.rewriteLoadCommands(changefunc): rewroteAny = True if rewroteAny: old_mode = flipwritable(fn) try: - with open(fn, 'rb+') as f: - for header in node.headers: + with open(fn, "rb+") as f: + for _header in node.headers: f.seek(0) node.write(f) f.seek(0, 2) diff --git a/lib/spack/external/macholib/SymbolTable.py b/lib/spack/external/macholib/SymbolTable.py index bf4d383ab7..006abab59f 100644 --- a/lib/spack/external/macholib/SymbolTable.py +++ b/lib/spack/external/macholib/SymbolTable.py @@ -3,12 +3,20 @@ Class to read the symbol table from a Mach-O header """ from __future__ import with_statement -from macholib.mach_o import relocation_info, dylib_reference, dylib_module -from macholib.mach_o import dylib_table_of_contents, nlist, nlist_64 -from macholib.mach_o import MH_CIGAM_64, MH_MAGIC_64 import sys -__all__ = ['SymbolTable'] +from macholib.mach_o import ( + MH_CIGAM_64, + MH_MAGIC_64, + dylib_module, + dylib_reference, + dylib_table_of_contents, + nlist, + nlist_64, + relocation_info, +) + +__all__ = ["SymbolTable"] if sys.version_info[0] == 2: range = xrange # noqa: F821 @@ -21,7 +29,7 @@ class SymbolTable(object): if header is None: header = macho.headers[0] self.macho_header = header - with openfile(macho.filename, 'rb') as fh: + with openfile(macho.filename, "rb") as fh: self.symtab = header.getSymbolTableCommand() self.dysymtab = header.getDynamicSymbolTableCommand() @@ -43,22 +51,32 @@ class SymbolTable(object): else: cls = nlist - for i in range(cmd.nsyms): + for _i in range(cmd.nsyms): cmd = cls.from_fileobj(fh, _endian_=self.macho_header.endian) if cmd.n_un == 0: - nlists.append((cmd, '')) + nlists.append((cmd, "")) else: nlists.append( - (cmd, strtab[cmd.n_un:strtab.find(b'\x00', cmd.n_un)])) + ( + cmd, + strtab[cmd.n_un : strtab.find(b"\x00", cmd.n_un)], # noqa: E203 + ) + ) return nlists def readDynamicSymbolTable(self, fh): cmd = self.dysymtab nlists = self.nlists - self.localsyms = nlists[cmd.ilocalsym:cmd.ilocalsym+cmd.nlocalsym] - self.extdefsyms = nlists[cmd.iextdefsym:cmd.iextdefsym+cmd.nextdefsym] - self.undefsyms = nlists[cmd.iundefsym:cmd.iundefsym+cmd.nundefsym] + self.localsyms = nlists[ + cmd.ilocalsym : cmd.ilocalsym + cmd.nlocalsym # noqa: E203 + ] + self.extdefsyms = nlists[ + cmd.iextdefsym : cmd.iextdefsym + cmd.nextdefsym # noqa: E203 + ] + self.undefsyms = nlists[ + cmd.iundefsym : cmd.iundefsym + cmd.nundefsym # noqa: E203 + ] if cmd.tocoff == 0: self.toc = None else: @@ -75,7 +93,7 @@ class SymbolTable(object): def readsym(self, fh, off, n): fh.seek(self.macho_header.offset + off) refs = [] - for i in range(n): + for _i in range(n): ref = dylib_reference.from_fileobj(fh) isym, flags = divmod(ref.isym_flags, 256) refs.append((self.nlists[isym], flags)) diff --git a/lib/spack/external/macholib/__init__.py b/lib/spack/external/macholib/__init__.py index f77c79492b..f2945849f8 100644 --- a/lib/spack/external/macholib/__init__.py +++ b/lib/spack/external/macholib/__init__.py @@ -5,4 +5,4 @@ See the relevant header files in /usr/include/mach-o And also Apple's documentation. """ -__version__ = '1.10' +__version__ = "1.15.2" diff --git a/lib/spack/external/macholib/__main__.py b/lib/spack/external/macholib/__main__.py index 66eaad865c..dd3cc11610 100644 --- a/lib/spack/external/macholib/__main__.py +++ b/lib/spack/external/macholib/__main__.py @@ -1,26 +1,24 @@ -from __future__ import print_function, absolute_import +from __future__ import absolute_import, print_function + import os import sys +from macholib import macho_dump, macho_standalone from macholib.util import is_platform_file -from macholib import macho_dump -from macholib import macho_standalone gCommand = None def check_file(fp, path, callback): if not os.path.exists(path): - print( - '%s: %s: No such file or directory' % (gCommand, path), - file=sys.stderr) + print("%s: %s: No such file or directory" % (gCommand, path), file=sys.stderr) return 1 try: is_plat = is_platform_file(path) except IOError as msg: - print('%s: %s: %s' % (gCommand, path, msg), file=sys.stderr) + print("%s: %s: %s" % (gCommand, path, msg), file=sys.stderr) return 1 else: @@ -34,10 +32,9 @@ def walk_tree(callback, paths): for base in paths: if os.path.isdir(base): - for root, dirs, files in os.walk(base): + for root, _dirs, files in os.walk(base): for fn in files: - err |= check_file( - sys.stdout, os.path.join(root, fn), callback) + err |= check_file(sys.stdout, os.path.join(root, fn), callback) else: err |= check_file(sys.stdout, base, callback) @@ -60,17 +57,17 @@ def main(): gCommand = sys.argv[1] - if gCommand == 'dump': + if gCommand == "dump": walk_tree(macho_dump.print_file, sys.argv[2:]) - elif gCommand == 'find': + elif gCommand == "find": walk_tree(lambda fp, path: print(path, file=fp), sys.argv[2:]) - elif gCommand == 'standalone': + elif gCommand == "standalone": for dn in sys.argv[2:]: macho_standalone.standaloneApp(dn) - elif gCommand in ('help', '--help'): + elif gCommand in ("help", "--help"): print_usage(sys.stdout) sys.exit(0) diff --git a/lib/spack/external/macholib/_cmdline.py b/lib/spack/external/macholib/_cmdline.py index c6227334a1..9304fb6257 100644 --- a/lib/spack/external/macholib/_cmdline.py +++ b/lib/spack/external/macholib/_cmdline.py @@ -1,7 +1,8 @@ """ Internal helpers for basic commandline tools """ -from __future__ import print_function, absolute_import +from __future__ import absolute_import, print_function + import os import sys @@ -10,15 +11,16 @@ from macholib.util import is_platform_file def check_file(fp, path, callback): if not os.path.exists(path): - print('%s: %s: No such file or directory' % ( - sys.argv[0], path), file=sys.stderr) + print( + "%s: %s: No such file or directory" % (sys.argv[0], path), file=sys.stderr + ) return 1 try: is_plat = is_platform_file(path) except IOError as msg: - print('%s: %s: %s' % (sys.argv[0], path, msg), file=sys.stderr) + print("%s: %s: %s" % (sys.argv[0], path, msg), file=sys.stderr) return 1 else: @@ -38,10 +40,9 @@ def main(callback): for base in args: if os.path.isdir(base): - for root, dirs, files in os.walk(base): + for root, _dirs, files in os.walk(base): for fn in files: - err |= check_file( - sys.stdout, os.path.join(root, fn), callback) + err |= check_file(sys.stdout, os.path.join(root, fn), callback) else: err |= check_file(sys.stdout, base, callback) diff --git a/lib/spack/external/macholib/dyld.py b/lib/spack/external/macholib/dyld.py index 1157ebf007..5282a08d42 100644 --- a/lib/spack/external/macholib/dyld.py +++ b/lib/spack/external/macholib/dyld.py @@ -2,18 +2,45 @@ dyld emulation """ -from itertools import chain - +import ctypes import os +import platform import sys +from itertools import chain -from macholib.framework import framework_info from macholib.dylib import dylib_info +from macholib.framework import framework_info -__all__ = [ - 'dyld_find', 'framework_find', - 'framework_info', 'dylib_info', -] +__all__ = ["dyld_find", "framework_find", "framework_info", "dylib_info"] + +if sys.platform == "darwin" and [ + int(x) for x in platform.mac_ver()[0].split(".")[:2] +] >= [10, 16]: + try: + libc = ctypes.CDLL("libSystem.dylib") + + except OSError: + _dyld_shared_cache_contains_path = None + + else: + try: + _dyld_shared_cache_contains_path = libc._dyld_shared_cache_contains_path + except AttributeError: + _dyld_shared_cache_contains_path = None + + else: + _dyld_shared_cache_contains_path.restype = ctypes.c_bool + _dyld_shared_cache_contains_path.argtypes = [ctypes.c_char_p] + + if sys.version_info[0] != 2: + __dyld_shared_cache_contains_path = _dyld_shared_cache_contains_path + + def _dyld_shared_cache_contains_path(path): + return __dyld_shared_cache_contains_path(path.encode()) + + +else: + _dyld_shared_cache_contains_path = None # These are the defaults as per man dyld(1) # @@ -31,13 +58,16 @@ _DEFAULT_LIBRARY_FALLBACK = [ "/usr/lib", ] -# XXX: Is this function still needed? if sys.version_info[0] == 2: + def _ensure_utf8(s): if isinstance(s, unicode): # noqa: F821 - return s.encode('utf8') + return s.encode("utf8") return s + + else: + def _ensure_utf8(s): if s is not None and not isinstance(s, str): raise ValueError(s) @@ -48,31 +78,31 @@ def _dyld_env(env, var): if env is None: env = os.environ rval = env.get(var) - if rval is None or rval == '': + if rval is None or rval == "": return [] - return rval.split(':') + return rval.split(":") def dyld_image_suffix(env=None): if env is None: env = os.environ - return env.get('DYLD_IMAGE_SUFFIX') + return env.get("DYLD_IMAGE_SUFFIX") def dyld_framework_path(env=None): - return _dyld_env(env, 'DYLD_FRAMEWORK_PATH') + return _dyld_env(env, "DYLD_FRAMEWORK_PATH") def dyld_library_path(env=None): - return _dyld_env(env, 'DYLD_LIBRARY_PATH') + return _dyld_env(env, "DYLD_LIBRARY_PATH") def dyld_fallback_framework_path(env=None): - return _dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH') + return _dyld_env(env, "DYLD_FALLBACK_FRAMEWORK_PATH") def dyld_fallback_library_path(env=None): - return _dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH') + return _dyld_env(env, "DYLD_FALLBACK_LIBRARY_PATH") def dyld_image_suffix_search(iterator, env=None): @@ -83,8 +113,8 @@ def dyld_image_suffix_search(iterator, env=None): def _inject(iterator=iterator, suffix=suffix): for path in iterator: - if path.endswith('.dylib'): - yield path[:-len('.dylib')] + suffix + '.dylib' + if path.endswith(".dylib"): + yield path[: -len(".dylib")] + suffix + ".dylib" else: yield path + suffix yield path @@ -102,7 +132,7 @@ def dyld_override_search(name, env=None): if framework is not None: for path in dyld_framework_path(env): - yield os.path.join(path, framework['name']) + yield os.path.join(path, framework["name"]) # If DYLD_LIBRARY_PATH is set then use the first file that exists # in the path. If none use the original name. @@ -114,16 +144,18 @@ def dyld_executable_path_search(name, executable_path=None): # If we haven't done any searching and found a library and the # dylib_name starts with "@executable_path/" then construct the # library name. - if name.startswith('@executable_path/') and executable_path is not None: - yield os.path.join(executable_path, name[len('@executable_path/'):]) + if name.startswith("@executable_path/") and executable_path is not None: + yield os.path.join( + executable_path, name[len("@executable_path/") :] # noqa: E203 + ) def dyld_loader_search(name, loader_path=None): # If we haven't done any searching and found a library and the # dylib_name starts with "@loader_path/" then construct the # library name. - if name.startswith('@loader_path/') and loader_path is not None: - yield os.path.join(loader_path, name[len('@loader_path/'):]) + if name.startswith("@loader_path/") and loader_path is not None: + yield os.path.join(loader_path, name[len("@loader_path/") :]) # noqa: E203 def dyld_default_search(name, env=None): @@ -136,11 +168,11 @@ def dyld_default_search(name, env=None): if fallback_framework_path: for path in fallback_framework_path: - yield os.path.join(path, framework['name']) + yield os.path.join(path, framework["name"]) else: for path in _DEFAULT_FRAMEWORK_FALLBACK: - yield os.path.join(path, framework['name']) + yield os.path.join(path, framework["name"]) fallback_library_path = dyld_fallback_library_path(env) if fallback_library_path: @@ -158,12 +190,20 @@ def dyld_find(name, executable_path=None, env=None, loader_path=None): """ name = _ensure_utf8(name) executable_path = _ensure_utf8(executable_path) - for path in dyld_image_suffix_search(chain( - dyld_override_search(name, env), - dyld_executable_path_search(name, executable_path), - dyld_loader_search(name, loader_path), - dyld_default_search(name, env), - ), env): + for path in dyld_image_suffix_search( + chain( + dyld_override_search(name, env), + dyld_executable_path_search(name, executable_path), + dyld_loader_search(name, loader_path), + dyld_default_search(name, env), + ), + env, + ): + if ( + _dyld_shared_cache_contains_path is not None + and _dyld_shared_cache_contains_path(path) + ): + return path if os.path.isfile(path): return path raise ValueError("dylib %s could not be found" % (name,)) @@ -182,9 +222,9 @@ def framework_find(fn, executable_path=None, env=None): return dyld_find(fn, executable_path=executable_path, env=env) except ValueError: pass - fmwk_index = fn.rfind('.framework') + fmwk_index = fn.rfind(".framework") if fmwk_index == -1: fmwk_index = len(fn) - fn += '.framework' + fn += ".framework" fn = os.path.join(fn, os.path.basename(fn[:fmwk_index])) return dyld_find(fn, executable_path=executable_path, env=env) diff --git a/lib/spack/external/macholib/dylib.py b/lib/spack/external/macholib/dylib.py index 5b06b40e13..72301a8f19 100644 --- a/lib/spack/external/macholib/dylib.py +++ b/lib/spack/external/macholib/dylib.py @@ -4,9 +4,10 @@ Generic dylib path manipulation import re -__all__ = ['dylib_info'] +__all__ = ["dylib_info"] -_DYLIB_RE = re.compile(r"""(?x) +_DYLIB_RE = re.compile( + r"""(?x) (?P^.*)(?:^|/) (?P (?P\w+?) @@ -14,7 +15,8 @@ _DYLIB_RE = re.compile(r"""(?x) (?:_(?P[^._]+))? \.dylib$ ) -""") +""" +) def dylib_info(filename): diff --git a/lib/spack/external/macholib/framework.py b/lib/spack/external/macholib/framework.py index 8f8632c209..027001e413 100644 --- a/lib/spack/external/macholib/framework.py +++ b/lib/spack/external/macholib/framework.py @@ -4,9 +4,10 @@ Generic framework path manipulation import re -__all__ = ['framework_info'] +__all__ = ["framework_info"] -_STRICT_FRAMEWORK_RE = re.compile(r"""(?x) +_STRICT_FRAMEWORK_RE = re.compile( + r"""(?x) (?P^.*)(?:^|/) (?P (?P[-_A-Za-z0-9]+).framework/ @@ -14,7 +15,8 @@ _STRICT_FRAMEWORK_RE = re.compile(r"""(?x) (?P=shortname) (?:_(?P[^_]+))? )$ -""") +""" +) def framework_info(filename): diff --git a/lib/spack/external/macholib/itergraphreport.py b/lib/spack/external/macholib/itergraphreport.py index eea3fd69bc..08692c057c 100644 --- a/lib/spack/external/macholib/itergraphreport.py +++ b/lib/spack/external/macholib/itergraphreport.py @@ -1,7 +1,5 @@ """ Utilities for creating dot output from a MachOGraph - -XXX: need to rewrite this based on altgraph.Dot """ from collections import deque @@ -11,28 +9,28 @@ try: except ImportError: imap = map -__all__ = ['itergraphreport'] +__all__ = ["itergraphreport"] -def itergraphreport(nodes, describe_edge, name='G'): +def itergraphreport(nodes, describe_edge, name="G"): edges = deque() nodetoident = {} def nodevisitor(node, data, outgoing, incoming): - return {'label': str(node)} + return {"label": str(node)} def edgevisitor(edge, data, head, tail): return {} - yield 'digraph %s {\n' % (name,) - attr = dict(rankdir='LR', concentrate='true') + yield "digraph %s {\n" % (name,) + attr = {"rankdir": "LR", "concentrate": "true"} cpatt = '%s="%s"' - for item in attr.iteritems(): - yield '\t%s;\n' % (cpatt % item,) + for item in attr.items(): + yield "\t%s;\n" % (cpatt % item,) # find all packages (subgraphs) - for (node, data, outgoing, incoming) in nodes: - nodetoident[node] = getattr(data, 'identifier', node) + for (node, data, _outgoing, _incoming) in nodes: + nodetoident[node] = getattr(data, "identifier", node) # create sets for subgraph, write out descriptions for (node, data, outgoing, incoming) in nodes: @@ -43,17 +41,19 @@ def itergraphreport(nodes, describe_edge, name='G'): # describe node yield '\t"%s" [%s];\n' % ( node, - ','.join([ - (cpatt % item) for item in - nodevisitor(node, data, outgoing, incoming).iteritems() - ]), + ",".join( + [ + (cpatt % item) + for item in nodevisitor(node, data, outgoing, incoming).items() + ] + ), ) graph = [] while edges: edge, data, head, tail = edges.popleft() - if data in ('run_file', 'load_dylib'): + if data in ("run_file", "load_dylib"): graph.append((edge, data, head, tail)) def do_graph(edges, tabs): @@ -64,10 +64,10 @@ def itergraphreport(nodes, describe_edge, name='G'): yield edgestr % ( head, tail, - ','.join([(cpatt % item) for item in attribs.iteritems()]), + ",".join([(cpatt % item) for item in attribs.items()]), ) - for s in do_graph(graph, '\t'): + for s in do_graph(graph, "\t"): yield s - yield '}\n' + yield "}\n" diff --git a/lib/spack/external/macholib/mach_o.py b/lib/spack/external/macholib/mach_o.py index 7c5803d939..7768ee38d2 100644 --- a/lib/spack/external/macholib/mach_o.py +++ b/lib/spack/external/macholib/mach_o.py @@ -13,28 +13,38 @@ See /usr/include/mach-o and friends. import time -from macholib.ptypes import p_uint32, p_uint64, Structure, p_long, pypackable -from macholib.ptypes import p_int64, p_short, p_uint8, p_int32, p_ulong +from macholib.ptypes import ( + Structure, + p_int32, + p_int64, + p_long, + p_short, + p_uint8, + p_uint32, + p_uint64, + p_ulong, + pypackable, +) _CPU_ARCH_ABI64 = 0x01000000 CPU_TYPE_NAMES = { - -1: 'ANY', - 1: 'VAX', - 6: 'MC680x0', - 7: 'i386', - _CPU_ARCH_ABI64 | 7: 'x86_64', - 8: 'MIPS', - 10: 'MC98000', - 11: 'HPPA', - 12: 'ARM', - _CPU_ARCH_ABI64 | 12: 'ARM64', - 13: 'MC88000', - 14: 'SPARC', - 15: 'i860', - 16: 'Alpha', - 18: 'PowerPC', - _CPU_ARCH_ABI64 | 18: 'PowerPC64', + -1: "ANY", + 1: "VAX", + 6: "MC680x0", + 7: "i386", + _CPU_ARCH_ABI64 | 7: "x86_64", + 8: "MIPS", + 10: "MC98000", + 11: "HPPA", + 12: "ARM", + _CPU_ARCH_ABI64 | 12: "ARM64", + 13: "MC88000", + 14: "SPARC", + 15: "i860", + 16: "Alpha", + 18: "PowerPC", + _CPU_ARCH_ABI64 | 18: "PowerPC64", } INTEL64_SUBTYPE = { @@ -65,13 +75,13 @@ INTEL_SUBTYPE = { 132: "CPU_SUBTYPE_486SX", 166: "CPU_SUBTYPE_PENTII_M5", 199: "CPU_SUBTYPE_CELERON", - 231: "CPU_SUBTYPE_CELERON_MOBILE" + 231: "CPU_SUBTYPE_CELERON_MOBILE", } MC680_SUBTYPE = { 1: "CPU_SUBTYPE_MC680x0_ALL", 2: "CPU_SUBTYPE_MC68040", - 3: "CPU_SUBTYPE_MC68030_ONLY" + 3: "CPU_SUBTYPE_MC68030_ONLY", } MIPS_SUBTYPE = { @@ -82,33 +92,22 @@ MIPS_SUBTYPE = { 4: "CPU_SUBTYPE_MIPS_R2000a", 5: "CPU_SUBTYPE_MIPS_R2000", 6: "CPU_SUBTYPE_MIPS_R3000a", - 7: "CPU_SUBTYPE_MIPS_R3000" + 7: "CPU_SUBTYPE_MIPS_R3000", } -MC98000_SUBTYPE = { - 0: "CPU_SUBTYPE_MC98000_ALL", - 1: "CPU_SUBTYPE_MC98601" -} +MC98000_SUBTYPE = {0: "CPU_SUBTYPE_MC98000_ALL", 1: "CPU_SUBTYPE_MC98601"} -HPPA_SUBTYPE = { - 0: "CPU_SUBTYPE_HPPA_7100", - 1: "CPU_SUBTYPE_HPPA_7100LC" -} +HPPA_SUBTYPE = {0: "CPU_SUBTYPE_HPPA_7100", 1: "CPU_SUBTYPE_HPPA_7100LC"} MC88_SUBTYPE = { 0: "CPU_SUBTYPE_MC88000_ALL", 1: "CPU_SUBTYPE_MC88100", - 2: "CPU_SUBTYPE_MC88110" + 2: "CPU_SUBTYPE_MC88110", } -SPARC_SUBTYPE = { - 0: "CPU_SUBTYPE_SPARC_ALL" -} +SPARC_SUBTYPE = {0: "CPU_SUBTYPE_SPARC_ALL"} -I860_SUBTYPE = { - 0: "CPU_SUBTYPE_I860_ALL", - 1: "CPU_SUBTYPE_I860_860" -} +I860_SUBTYPE = {0: "CPU_SUBTYPE_I860_ALL", 1: "CPU_SUBTYPE_I860_860"} POWERPC_SUBTYPE = { 0: "CPU_SUBTYPE_POWERPC_ALL", @@ -123,7 +122,7 @@ POWERPC_SUBTYPE = { 9: "CPU_SUBTYPE_POWERPC_750", 10: "CPU_SUBTYPE_POWERPC_7400", 11: "CPU_SUBTYPE_POWERPC_7450", - 100: "CPU_SUBTYPE_POWERPC_970" + 100: "CPU_SUBTYPE_POWERPC_970", } ARM_SUBTYPE = { @@ -142,10 +141,7 @@ ARM_SUBTYPE = { 16: "CPU_SUBTYPE_ARM_V7EM", } -ARM64_SUBTYPE = { - 0: "CPU_SUBTYPE_ARM64_ALL", - 1: "CPU_SUBTYPE_ARM64_V8", -} +ARM64_SUBTYPE = {0: "CPU_SUBTYPE_ARM64_ALL", 1: "CPU_SUBTYPE_ARM64_V8"} VAX_SUBTYPE = { 0: "CPU_SUBTYPE_VAX_ALL", @@ -165,7 +161,7 @@ VAX_SUBTYPE = { def get_cpu_subtype(cpu_type, cpu_subtype): - st = cpu_subtype & 0x0fffffff + st = cpu_subtype & 0x0FFFFFFF if cpu_type == 1: subtype = VAX_SUBTYPE.get(st, st) @@ -213,165 +209,181 @@ _MH_DYLINKER_SYM = "__mh_dylinker_header" MH_DYLINKER_SYM = "_mh_dylinker_header" ( - MH_OBJECT, MH_EXECUTE, MH_FVMLIB, MH_CORE, MH_PRELOAD, MH_DYLIB, - MH_DYLINKER, MH_BUNDLE, MH_DYLIB_STUB, MH_DSYM -) = range(0x1, 0xb) + MH_OBJECT, + MH_EXECUTE, + MH_FVMLIB, + MH_CORE, + MH_PRELOAD, + MH_DYLIB, + MH_DYLINKER, + MH_BUNDLE, + MH_DYLIB_STUB, + MH_DSYM, +) = range(0x1, 0xB) + +MH_FILESET = 0xC ( - MH_NOUNDEFS, MH_INCRLINK, MH_DYLDLINK, MH_BINDATLOAD, MH_PREBOUND, - MH_SPLIT_SEGS, MH_LAZY_INIT, MH_TWOLEVEL, MH_FORCE_FLAT, MH_NOMULTIDEFS, - MH_NOFIXPREBINDING, MH_PREBINDABLE, MH_ALLMODSBOUND, - MH_SUBSECTIONS_VIA_SYMBOLS, MH_CANONICAL, MH_WEAK_DEFINES, - MH_BINDS_TO_WEAK, MH_ALLOW_STACK_EXECUTION, - MH_ROOT_SAFE, MH_SETUID_SAFE, MH_NO_REEXPORTED_DYLIBS, MH_PIE, - MH_DEAD_STRIPPABLE_DYLIB, MH_HAS_TLV_DESCRIPTORS, MH_NO_HEAP_EXECUTION, - MH_APP_EXTENSION_SAFE + MH_NOUNDEFS, + MH_INCRLINK, + MH_DYLDLINK, + MH_BINDATLOAD, + MH_PREBOUND, + MH_SPLIT_SEGS, + MH_LAZY_INIT, + MH_TWOLEVEL, + MH_FORCE_FLAT, + MH_NOMULTIDEFS, + MH_NOFIXPREBINDING, + MH_PREBINDABLE, + MH_ALLMODSBOUND, + MH_SUBSECTIONS_VIA_SYMBOLS, + MH_CANONICAL, + MH_WEAK_DEFINES, + MH_BINDS_TO_WEAK, + MH_ALLOW_STACK_EXECUTION, + MH_ROOT_SAFE, + MH_SETUID_SAFE, + MH_NO_REEXPORTED_DYLIBS, + MH_PIE, + MH_DEAD_STRIPPABLE_DYLIB, + MH_HAS_TLV_DESCRIPTORS, + MH_NO_HEAP_EXECUTION, + MH_APP_EXTENSION_SAFE, ) = map((1).__lshift__, range(26)) -MH_MAGIC = 0xfeedface -MH_CIGAM = 0xcefaedfe -MH_MAGIC_64 = 0xfeedfacf -MH_CIGAM_64 = 0xcffaedfe +MH_MAGIC = 0xFEEDFACE +MH_CIGAM = 0xCEFAEDFE +MH_MAGIC_64 = 0xFEEDFACF +MH_CIGAM_64 = 0xCFFAEDFE integer_t = p_int32 cpu_type_t = integer_t cpu_subtype_t = p_uint32 MH_FILETYPE_NAMES = { - MH_OBJECT: 'relocatable object', - MH_EXECUTE: 'demand paged executable', - MH_FVMLIB: 'fixed vm shared library', - MH_CORE: 'core', - MH_PRELOAD: 'preloaded executable', - MH_DYLIB: 'dynamically bound shared library', - MH_DYLINKER: 'dynamic link editor', - MH_BUNDLE: 'dynamically bound bundle', - MH_DYLIB_STUB: 'shared library stub for static linking', - MH_DSYM: 'symbol information', + MH_OBJECT: "relocatable object", + MH_EXECUTE: "demand paged executable", + MH_FVMLIB: "fixed vm shared library", + MH_CORE: "core", + MH_PRELOAD: "preloaded executable", + MH_DYLIB: "dynamically bound shared library", + MH_DYLINKER: "dynamic link editor", + MH_BUNDLE: "dynamically bound bundle", + MH_DYLIB_STUB: "shared library stub for static linking", + MH_DSYM: "symbol information", + MH_FILESET: "fileset object", } MH_FILETYPE_SHORTNAMES = { - MH_OBJECT: 'object', - MH_EXECUTE: 'execute', - MH_FVMLIB: 'fvmlib', - MH_CORE: 'core', - MH_PRELOAD: 'preload', - MH_DYLIB: 'dylib', - MH_DYLINKER: 'dylinker', - MH_BUNDLE: 'bundle', - MH_DYLIB_STUB: 'dylib_stub', - MH_DSYM: 'dsym', + MH_OBJECT: "object", + MH_EXECUTE: "execute", + MH_FVMLIB: "fvmlib", + MH_CORE: "core", + MH_PRELOAD: "preload", + MH_DYLIB: "dylib", + MH_DYLINKER: "dylinker", + MH_BUNDLE: "bundle", + MH_DYLIB_STUB: "dylib_stub", + MH_DSYM: "dsym", } MH_FLAGS_NAMES = { - 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_NOFIXPREBINDING: 'MH_NOFIXPREBINDING', - 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', + 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_NOFIXPREBINDING: "MH_NOFIXPREBINDING", + 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", } MH_FLAGS_DESCRIPTIONS = { - MH_NOUNDEFS: 'no undefined references', - MH_INCRLINK: 'output of an incremental link', - MH_DYLDLINK: 'input for the dynamic linker', - MH_BINDATLOAD: 'undefined references bound dynamically when loaded', - MH_PREBOUND: 'dynamic undefined references prebound', - MH_SPLIT_SEGS: 'split read-only and read-write segments', - MH_LAZY_INIT: '(obsolete)', - MH_TWOLEVEL: 'using two-level name space bindings', - MH_FORCE_FLAT: 'forcing all imagges to use flat name space bindings', - MH_NOMULTIDEFS: 'umbrella guarantees no multiple definitions', - MH_NOFIXPREBINDING: 'do not notify prebinding agent about this executable', - MH_PREBINDABLE: - 'the binary is not prebound but can have its prebinding redone', - MH_ALLMODSBOUND: - 'indicates that this binary binds to all two-level namespace modules ' - 'of its dependent libraries', - MH_SUBSECTIONS_VIA_SYMBOLS: - 'safe to divide up the sections into sub-sections via symbols for ' - 'dead code stripping', - MH_CANONICAL: - 'the binary has been canonicalized via the unprebind operation', - MH_WEAK_DEFINES: 'the final linked image contains external weak symbols', - MH_BINDS_TO_WEAK: 'the final linked image uses weak symbols', - MH_ALLOW_STACK_EXECUTION: - 'all stacks in the task will be given stack execution privilege', - MH_ROOT_SAFE: - 'the binary declares it is safe for use in processes with uid zero', - MH_SETUID_SAFE: - 'the binary declares it is safe for use in processes when issetugid() ' - 'is true', - MH_NO_REEXPORTED_DYLIBS: - 'the static linker does not need to examine dependent dylibs to see ' - 'if any are re-exported', - MH_PIE: 'the OS will load the main executable at a random address', - MH_DEAD_STRIPPABLE_DYLIB: - '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', - MH_HAS_TLV_DESCRIPTORS: - 'contains a section of type S_THREAD_LOCAL_VARIABLES', - MH_NO_HEAP_EXECUTION: - 'the OS will run the main executable with a non-executable heap ' - 'even on platforms that don\'t require it', - MH_APP_EXTENSION_SAFE: - 'the code was linked for use in an application extension.', + MH_NOUNDEFS: "no undefined references", + MH_INCRLINK: "output of an incremental link", + MH_DYLDLINK: "input for the dynamic linker", + MH_BINDATLOAD: "undefined references bound dynamically when loaded", + MH_PREBOUND: "dynamic undefined references prebound", + MH_SPLIT_SEGS: "split read-only and read-write segments", + MH_LAZY_INIT: "(obsolete)", + MH_TWOLEVEL: "using two-level name space bindings", + MH_FORCE_FLAT: "forcing all imagges to use flat name space bindings", + MH_NOMULTIDEFS: "umbrella guarantees no multiple definitions", + MH_NOFIXPREBINDING: "do not notify prebinding agent about this executable", + MH_PREBINDABLE: "the binary is not prebound but can have its prebinding redone", + MH_ALLMODSBOUND: "indicates that this binary binds to all " + "two-level namespace modules of its dependent libraries", + MH_SUBSECTIONS_VIA_SYMBOLS: "safe to divide up the sections into " + "sub-sections via symbols for dead code stripping", + MH_CANONICAL: "the binary has been canonicalized via the unprebind operation", + MH_WEAK_DEFINES: "the final linked image contains external weak symbols", + MH_BINDS_TO_WEAK: "the final linked image uses weak symbols", + MH_ALLOW_STACK_EXECUTION: "all stacks in the task will be given " + "stack execution privilege", + MH_ROOT_SAFE: "the binary declares it is safe for use in processes with uid zero", + MH_SETUID_SAFE: "the binary declares it is safe for use in processes " + "when issetugid() is true", + MH_NO_REEXPORTED_DYLIBS: "the static linker does not need to examine dependent " + "dylibs to see if any are re-exported", + MH_PIE: "the OS will load the main executable at a random address", + MH_DEAD_STRIPPABLE_DYLIB: "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", + MH_HAS_TLV_DESCRIPTORS: "contains a section of type S_THREAD_LOCAL_VARIABLES", + MH_NO_HEAP_EXECUTION: "the OS will run the main executable with a " + "non-executable heap even on platforms that don't require it", + MH_APP_EXTENSION_SAFE: "the code was linked for use in an application extension.", } class mach_version_helper(Structure): - _fields_ = ( - ('_version', p_uint32), - ) + _fields_ = (("_version", p_uint32),) @property def major(self): - return self._version >> 16 & 0xffff + return self._version >> 16 & 0xFFFF @major.setter def major(self, v): - self._version = (self._version & 0xffff) | (v << 16) + self._version = (self._version & 0xFFFF) | (v << 16) @property def minor(self): - return self._version >> 8 & 0xff + return self._version >> 8 & 0xFF @minor.setter def minor(self, v): - self._version = (self._version & 0xffff00ff) | (v << 8) + self._version = (self._version & 0xFFFF00FF) | (v << 8) @property def rev(self): - return self._version & 0xff + return self._version & 0xFF @rev.setter def rev(self, v): - return (self._version & 0xffffff00) | v + return (self._version & 0xFFFFFF00) | v def __str__(self): - return '%s.%s.%s' % (self.major, self.minor, self.rev) + return "%s.%s.%s" % (self.major, self.minor, self.rev) class mach_timestamp_helper(p_uint32): @@ -385,13 +397,13 @@ def read_struct(f, s, **kw): class mach_header(Structure): _fields_ = ( - ('magic', p_uint32), - ('cputype', cpu_type_t), - ('cpusubtype', cpu_subtype_t), - ('filetype', p_uint32), - ('ncmds', p_uint32), - ('sizeofcmds', p_uint32), - ('flags', p_uint32), + ("magic", p_uint32), + ("cputype", cpu_type_t), + ("cpusubtype", cpu_subtype_t), + ("filetype", p_uint32), + ("ncmds", p_uint32), + ("sizeofcmds", p_uint32), + ("flags", p_uint32), ) def _describe(self): @@ -400,38 +412,35 @@ class mach_header(Structure): dflags = [] while flags and bit < (1 << 32): if flags & bit: - dflags.append({ - 'name': MH_FLAGS_NAMES.get(bit, str(bit)), - 'description': MH_FLAGS_DESCRIPTIONS.get(bit, str(bit)) - }) + dflags.append( + { + "name": MH_FLAGS_NAMES.get(bit, str(bit)), + "description": MH_FLAGS_DESCRIPTIONS.get(bit, str(bit)), + } + ) flags = flags ^ bit bit <<= 1 return ( - ('magic', int(self.magic)), - ('cputype_string', CPU_TYPE_NAMES.get(self.cputype, self.cputype)), - ('cputype', int(self.cputype)), - ('cpusubtype_string', - get_cpu_subtype(self.cputype, self.cpusubtype)), - ('cpusubtype', int(self.cpusubtype)), - ('filetype_string', - MH_FILETYPE_NAMES.get(self.filetype, self.filetype)), - ('filetype', int(self.filetype)), - ('ncmds', self.ncmds), - ('sizeofcmds', self.sizeofcmds), - ('flags', dflags), - ('raw_flags', int(self.flags)) + ("magic", int(self.magic)), + ("cputype_string", CPU_TYPE_NAMES.get(self.cputype, self.cputype)), + ("cputype", int(self.cputype)), + ("cpusubtype_string", get_cpu_subtype(self.cputype, self.cpusubtype)), + ("cpusubtype", int(self.cpusubtype)), + ("filetype_string", MH_FILETYPE_NAMES.get(self.filetype, self.filetype)), + ("filetype", int(self.filetype)), + ("ncmds", self.ncmds), + ("sizeofcmds", self.sizeofcmds), + ("flags", dflags), + ("raw_flags", int(self.flags)), ) class mach_header_64(mach_header): - _fields_ = mach_header._fields_ + (('reserved', p_uint32),) + _fields_ = mach_header._fields_ + (("reserved", p_uint32),) class load_command(Structure): - _fields_ = ( - ('cmd', p_uint32), - ('cmdsize', p_uint32), - ) + _fields_ = (("cmd", p_uint32), ("cmdsize", p_uint32)) def get_cmd_name(self): return LC_NAMES.get(self.cmd, self.cmd) @@ -440,22 +449,40 @@ class load_command(Structure): LC_REQ_DYLD = 0x80000000 ( - LC_SEGMENT, LC_SYMTAB, LC_SYMSEG, LC_THREAD, LC_UNIXTHREAD, LC_LOADFVMLIB, - LC_IDFVMLIB, LC_IDENT, LC_FVMFILE, LC_PREPAGE, LC_DYSYMTAB, LC_LOAD_DYLIB, - LC_ID_DYLIB, LC_LOAD_DYLINKER, LC_ID_DYLINKER, LC_PREBOUND_DYLIB, - LC_ROUTINES, LC_SUB_FRAMEWORK, LC_SUB_UMBRELLA, LC_SUB_CLIENT, - LC_SUB_LIBRARY, LC_TWOLEVEL_HINTS, LC_PREBIND_CKSUM + LC_SEGMENT, + LC_SYMTAB, + LC_SYMSEG, + LC_THREAD, + LC_UNIXTHREAD, + LC_LOADFVMLIB, + LC_IDFVMLIB, + LC_IDENT, + LC_FVMFILE, + LC_PREPAGE, + LC_DYSYMTAB, + LC_LOAD_DYLIB, + LC_ID_DYLIB, + LC_LOAD_DYLINKER, + LC_ID_DYLINKER, + LC_PREBOUND_DYLIB, + LC_ROUTINES, + LC_SUB_FRAMEWORK, + LC_SUB_UMBRELLA, + LC_SUB_CLIENT, + LC_SUB_LIBRARY, + LC_TWOLEVEL_HINTS, + LC_PREBIND_CKSUM, ) = range(0x1, 0x18) LC_LOAD_WEAK_DYLIB = LC_REQ_DYLD | 0x18 LC_SEGMENT_64 = 0x19 -LC_ROUTINES_64 = 0x1a -LC_UUID = 0x1b -LC_RPATH = (0x1c | LC_REQ_DYLD) -LC_CODE_SIGNATURE = 0x1d -LC_CODE_SEGMENT_SPLIT_INFO = 0x1e -LC_REEXPORT_DYLIB = 0x1f | LC_REQ_DYLD +LC_ROUTINES_64 = 0x1A +LC_UUID = 0x1B +LC_RPATH = 0x1C | LC_REQ_DYLD +LC_CODE_SIGNATURE = 0x1D +LC_CODE_SEGMENT_SPLIT_INFO = 0x1E +LC_REEXPORT_DYLIB = 0x1F | LC_REQ_DYLD LC_LAZY_LOAD_DYLIB = 0x20 LC_ENCRYPTION_INFO = 0x21 LC_DYLD_INFO = 0x22 @@ -467,15 +494,18 @@ LC_FUNCTION_STARTS = 0x26 LC_DYLD_ENVIRONMENT = 0x27 LC_MAIN = 0x28 | LC_REQ_DYLD LC_DATA_IN_CODE = 0x29 -LC_SOURCE_VERSION = 0x2a -LC_DYLIB_CODE_SIGN_DRS = 0x2b -LC_ENCRYPTION_INFO_64 = 0x2c -LC_LINKER_OPTION = 0x2d -LC_LINKER_OPTIMIZATION_HINT = 0x2e -LC_VERSION_MIN_TVOS = 0x2f +LC_SOURCE_VERSION = 0x2A +LC_DYLIB_CODE_SIGN_DRS = 0x2B +LC_ENCRYPTION_INFO_64 = 0x2C +LC_LINKER_OPTION = 0x2D +LC_LINKER_OPTIMIZATION_HINT = 0x2E +LC_VERSION_MIN_TVOS = 0x2F LC_VERSION_MIN_WATCHOS = 0x30 LC_NOTE = 0x31 LC_BUILD_VERSION = 0x32 +LC_DYLD_EXPORTS_TRIE = 0x33 | LC_REQ_DYLD +LC_DYLD_CHAINED_FIXUPS = 0x34 | LC_REQ_DYLD +LC_FILESET_ENTRY = 0x35 | LC_REQ_DYLD # this is really a union.. but whatever @@ -483,37 +513,37 @@ class lc_str(p_uint32): pass -p_str16 = pypackable('p_str16', bytes, '16s') +p_str16 = pypackable("p_str16", bytes, "16s") vm_prot_t = p_int32 class segment_command(Structure): _fields_ = ( - ('segname', p_str16), - ('vmaddr', p_uint32), - ('vmsize', p_uint32), - ('fileoff', p_uint32), - ('filesize', p_uint32), - ('maxprot', vm_prot_t), - ('initprot', vm_prot_t), - ('nsects', p_uint32), # read the section structures ? - ('flags', p_uint32), + ("segname", p_str16), + ("vmaddr", p_uint32), + ("vmsize", p_uint32), + ("fileoff", p_uint32), + ("filesize", p_uint32), + ("maxprot", vm_prot_t), + ("initprot", vm_prot_t), + ("nsects", p_uint32), # read the section structures ? + ("flags", p_uint32), ) def describe(self): s = {} - s['segname'] = self.segname.rstrip('\x00') - s['vmaddr'] = int(self.vmaddr) - s['vmsize'] = int(self.vmsize) - s['fileoff'] = int(self.fileoff) - s['filesize'] = int(self.filesize) - s['initprot'] = self.get_initial_virtual_memory_protections() - s['initprot_raw'] = int(self.initprot) - s['maxprot'] = self.get_max_virtual_memory_protections() - s['maxprot_raw'] = int(self.maxprot) - s['nsects'] = int(self.nsects) - s['flags'] = self.flags + s["segname"] = self.segname.rstrip("\x00") + s["vmaddr"] = int(self.vmaddr) + s["vmsize"] = int(self.vmsize) + s["fileoff"] = int(self.fileoff) + s["filesize"] = int(self.filesize) + s["initprot"] = self.get_initial_virtual_memory_protections() + s["initprot_raw"] = int(self.initprot) + s["maxprot"] = self.get_max_virtual_memory_protections() + s["maxprot_raw"] = int(self.maxprot) + s["nsects"] = int(self.nsects) + s["flags"] = self.flags return s def get_initial_virtual_memory_protections(self): @@ -543,30 +573,30 @@ class segment_command(Structure): class segment_command_64(Structure): _fields_ = ( - ('segname', p_str16), - ('vmaddr', p_uint64), - ('vmsize', p_uint64), - ('fileoff', p_uint64), - ('filesize', p_uint64), - ('maxprot', vm_prot_t), - ('initprot', vm_prot_t), - ('nsects', p_uint32), # read the section structures ? - ('flags', p_uint32), + ("segname", p_str16), + ("vmaddr", p_uint64), + ("vmsize", p_uint64), + ("fileoff", p_uint64), + ("filesize", p_uint64), + ("maxprot", vm_prot_t), + ("initprot", vm_prot_t), + ("nsects", p_uint32), # read the section structures ? + ("flags", p_uint32), ) def describe(self): s = {} - s['segname'] = self.segname.rstrip('\x00') - s['vmaddr'] = int(self.vmaddr) - s['vmsize'] = int(self.vmsize) - s['fileoff'] = int(self.fileoff) - s['filesize'] = int(self.filesize) - s['initprot'] = self.get_initial_virtual_memory_protections() - s['initprot_raw'] = int(self.initprot) - s['maxprot'] = self.get_max_virtual_memory_protections() - s['maxprot_raw'] = int(self.maxprot) - s['nsects'] = int(self.nsects) - s['flags'] = self.flags + s["segname"] = self.segname.rstrip("\x00") + s["vmaddr"] = int(self.vmaddr) + s["vmsize"] = int(self.vmsize) + s["fileoff"] = int(self.fileoff) + s["filesize"] = int(self.filesize) + s["initprot"] = self.get_initial_virtual_memory_protections() + s["initprot_raw"] = int(self.initprot) + s["maxprot"] = self.get_max_virtual_memory_protections() + s["maxprot_raw"] = int(self.maxprot) + s["nsects"] = int(self.nsects) + s["flags"] = self.flags return s def get_initial_virtual_memory_protections(self): @@ -602,40 +632,40 @@ SG_PROTECTED_VERSION_1 = 0x8 class section(Structure): _fields_ = ( - ('sectname', p_str16), - ('segname', p_str16), - ('addr', p_uint32), - ('size', p_uint32), - ('offset', p_uint32), - ('align', p_uint32), - ('reloff', p_uint32), - ('nreloc', p_uint32), - ('flags', p_uint32), - ('reserved1', p_uint32), - ('reserved2', p_uint32), + ("sectname", p_str16), + ("segname", p_str16), + ("addr", p_uint32), + ("size", p_uint32), + ("offset", p_uint32), + ("align", p_uint32), + ("reloff", p_uint32), + ("nreloc", p_uint32), + ("flags", p_uint32), + ("reserved1", p_uint32), + ("reserved2", p_uint32), ) def describe(self): s = {} - s['sectname'] = self.sectname.rstrip('\x00') - s['segname'] = self.segname.rstrip('\x00') - s['addr'] = int(self.addr) - s['size'] = int(self.size) - s['offset'] = int(self.offset) - s['align'] = int(self.align) - s['reloff'] = int(self.reloff) - s['nreloc'] = int(self.nreloc) + s["sectname"] = self.sectname.rstrip("\x00") + s["segname"] = self.segname.rstrip("\x00") + s["addr"] = int(self.addr) + s["size"] = int(self.size) + s["offset"] = int(self.offset) + s["align"] = int(self.align) + s["reloff"] = int(self.reloff) + s["nreloc"] = int(self.nreloc) f = {} - f['type'] = FLAG_SECTION_TYPES[int(self.flags) & 0xff] - f['attributes'] = [] + f["type"] = FLAG_SECTION_TYPES[int(self.flags) & 0xFF] + f["attributes"] = [] for k in FLAG_SECTION_ATTRIBUTES: if k & self.flags: - f['attributes'].append(FLAG_SECTION_ATTRIBUTES[k]) - if not f['attributes']: - del f['attributes'] - s['flags'] = f - s['reserved1'] = int(self.reserved1) - s['reserved2'] = int(self.reserved2) + f["attributes"].append(FLAG_SECTION_ATTRIBUTES[k]) + if not f["attributes"]: + del f["attributes"] + s["flags"] = f + s["reserved1"] = int(self.reserved1) + s["reserved2"] = int(self.reserved2) return s def add_section_data(self, data): @@ -644,50 +674,50 @@ class section(Structure): class section_64(Structure): _fields_ = ( - ('sectname', p_str16), - ('segname', p_str16), - ('addr', p_uint64), - ('size', p_uint64), - ('offset', p_uint32), - ('align', p_uint32), - ('reloff', p_uint32), - ('nreloc', p_uint32), - ('flags', p_uint32), - ('reserved1', p_uint32), - ('reserved2', p_uint32), - ('reserved3', p_uint32), + ("sectname", p_str16), + ("segname", p_str16), + ("addr", p_uint64), + ("size", p_uint64), + ("offset", p_uint32), + ("align", p_uint32), + ("reloff", p_uint32), + ("nreloc", p_uint32), + ("flags", p_uint32), + ("reserved1", p_uint32), + ("reserved2", p_uint32), + ("reserved3", p_uint32), ) def describe(self): s = {} - s['sectname'] = self.sectname.rstrip('\x00') - s['segname'] = self.segname.rstrip('\x00') - s['addr'] = int(self.addr) - s['size'] = int(self.size) - s['offset'] = int(self.offset) - s['align'] = int(self.align) - s['reloff'] = int(self.reloff) - s['nreloc'] = int(self.nreloc) + s["sectname"] = self.sectname.rstrip("\x00") + s["segname"] = self.segname.rstrip("\x00") + s["addr"] = int(self.addr) + s["size"] = int(self.size) + s["offset"] = int(self.offset) + s["align"] = int(self.align) + s["reloff"] = int(self.reloff) + s["nreloc"] = int(self.nreloc) f = {} - f['type'] = FLAG_SECTION_TYPES[int(self.flags) & 0xff] - f['attributes'] = [] + f["type"] = FLAG_SECTION_TYPES[int(self.flags) & 0xFF] + f["attributes"] = [] for k in FLAG_SECTION_ATTRIBUTES: if k & self.flags: - f['attributes'].append(FLAG_SECTION_ATTRIBUTES[k]) - if not f['attributes']: - del f['attributes'] - s['flags'] = f - s['reserved1'] = int(self.reserved1) - s['reserved2'] = int(self.reserved2) - s['reserved3'] = int(self.reserved3) + f["attributes"].append(FLAG_SECTION_ATTRIBUTES[k]) + if not f["attributes"]: + del f["attributes"] + s["flags"] = f + s["reserved1"] = int(self.reserved1) + s["reserved2"] = int(self.reserved2) + s["reserved3"] = int(self.reserved3) return s def add_section_data(self, data): self.section_data = data -SECTION_TYPE = 0xff -SECTION_ATTRIBUTES = 0xffffff00 +SECTION_TYPE = 0xFF +SECTION_ATTRIBUTES = 0xFFFFFF00 S_REGULAR = 0x0 S_ZEROFILL = 0x1 S_CSTRING_LITERALS = 0x2 @@ -698,12 +728,12 @@ S_NON_LAZY_SYMBOL_POINTERS = 0x6 S_LAZY_SYMBOL_POINTERS = 0x7 S_SYMBOL_STUBS = 0x8 S_MOD_INIT_FUNC_POINTERS = 0x9 -S_MOD_TERM_FUNC_POINTERS = 0xa -S_COALESCED = 0xb -S_GB_ZEROFILL = 0xc -S_INTERPOSING = 0xd -S_16BYTE_LITERALS = 0xe -S_DTRACE_DOF = 0xf +S_MOD_TERM_FUNC_POINTERS = 0xA +S_COALESCED = 0xB +S_GB_ZEROFILL = 0xC +S_INTERPOSING = 0xD +S_16BYTE_LITERALS = 0xE +S_DTRACE_DOF = 0xF S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10 S_THREAD_LOCAL_REGULAR = 0x11 S_THREAD_LOCAL_ZEROFILL = 0x12 @@ -733,11 +763,10 @@ FLAG_SECTION_TYPES = { S_THREAD_LOCAL_ZEROFILL: "S_THREAD_LOCAL_ZEROFILL", S_THREAD_LOCAL_VARIABLES: "S_THREAD_LOCAL_VARIABLES", S_THREAD_LOCAL_VARIABLE_POINTERS: "S_THREAD_LOCAL_VARIABLE_POINTERS", - S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: - "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS" + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS", } -SECTION_ATTRIBUTES_USR = 0xff000000 +SECTION_ATTRIBUTES_USR = 0xFF000000 S_ATTR_PURE_INSTRUCTIONS = 0x80000000 S_ATTR_NO_TOC = 0x40000000 S_ATTR_STRIP_STATIC_SYMS = 0x20000000 @@ -746,7 +775,7 @@ S_ATTR_LIVE_SUPPORT = 0x08000000 S_ATTR_SELF_MODIFYING_CODE = 0x04000000 S_ATTR_DEBUG = 0x02000000 -SECTION_ATTRIBUTES_SYS = 0x00ffff00 +SECTION_ATTRIBUTES_SYS = 0x00FFFF00 S_ATTR_SOME_INSTRUCTIONS = 0x00000400 S_ATTR_EXT_RELOC = 0x00000200 S_ATTR_LOC_RELOC = 0x00000100 @@ -761,7 +790,7 @@ FLAG_SECTION_ATTRIBUTES = { S_ATTR_DEBUG: "S_ATTR_DEBUG", S_ATTR_SOME_INSTRUCTIONS: "S_ATTR_SOME_INSTRUCTIONS", S_ATTR_EXT_RELOC: "S_ATTR_EXT_RELOC", - S_ATTR_LOC_RELOC: "S_ATTR_LOC_RELOC" + S_ATTR_LOC_RELOC: "S_ATTR_LOC_RELOC", } SEG_PAGEZERO = "__PAGEZERO" @@ -794,9 +823,9 @@ SEG_IMPORT = "__IMPORT" class fvmlib(Structure): _fields_ = ( - ('name', lc_str), - ('minor_version', mach_version_helper), - ('header_addr', p_uint32), + ("name", lc_str), + ("minor_version", mach_version_helper), + ("header_addr", p_uint32), ) @@ -805,16 +834,16 @@ class fvmlib_command(Structure): def describe(self): s = {} - s['header_addr'] = int(self.header_addr) + s["header_addr"] = int(self.header_addr) return s class dylib(Structure): _fields_ = ( - ('name', lc_str), - ('timestamp', mach_timestamp_helper), - ('current_version', mach_version_helper), - ('compatibility_version', mach_version_helper), + ("name", lc_str), + ("timestamp", mach_timestamp_helper), + ("current_version", mach_version_helper), + ("compatibility_version", mach_version_helper), ) @@ -824,203 +853,183 @@ class dylib_command(Structure): def describe(self): s = {} - s['timestamp'] = str(self.timestamp) - s['current_version'] = str(self.current_version) - s['compatibility_version'] = str(self.compatibility_version) + s["timestamp"] = str(self.timestamp) + s["current_version"] = str(self.current_version) + s["compatibility_version"] = str(self.compatibility_version) return s class sub_framework_command(Structure): - _fields_ = ( - ('umbrella', lc_str), - ) + _fields_ = (("umbrella", lc_str),) def describe(self): return {} class sub_client_command(Structure): - _fields_ = ( - ('client', lc_str), - ) + _fields_ = (("client", lc_str),) def describe(self): return {} class sub_umbrella_command(Structure): - _fields_ = ( - ('sub_umbrella', lc_str), - ) + _fields_ = (("sub_umbrella", lc_str),) def describe(self): return {} class sub_library_command(Structure): - _fields_ = ( - ('sub_library', lc_str), - ) + _fields_ = (("sub_library", lc_str),) def describe(self): return {} class prebound_dylib_command(Structure): - _fields_ = ( - ('name', lc_str), - ('nmodules', p_uint32), - ('linked_modules', lc_str), - ) + _fields_ = (("name", lc_str), ("nmodules", p_uint32), ("linked_modules", lc_str)) def describe(self): - return {'nmodules': int(self.nmodules)} + return {"nmodules": int(self.nmodules)} class dylinker_command(Structure): - _fields_ = ( - ('name', lc_str), - ) + _fields_ = (("name", lc_str),) def describe(self): return {} class thread_command(Structure): - _fields_ = ( - ('flavor', p_uint32), - ('count', p_uint32) - ) + _fields_ = (("flavor", p_uint32), ("count", p_uint32)) def describe(self): s = {} - s['flavor'] = int(self.flavor) - s['count'] = int(self.count) + s["flavor"] = int(self.flavor) + s["count"] = int(self.count) return s class entry_point_command(Structure): - _fields_ = ( - ('entryoff', p_uint64), - ('stacksize', p_uint64), - ) + _fields_ = (("entryoff", p_uint64), ("stacksize", p_uint64)) def describe(self): s = {} - s['entryoff'] = int(self.entryoff) - s['stacksize'] = int(self.stacksize) + s["entryoff"] = int(self.entryoff) + s["stacksize"] = int(self.stacksize) return s class routines_command(Structure): _fields_ = ( - ('init_address', p_uint32), - ('init_module', p_uint32), - ('reserved1', p_uint32), - ('reserved2', p_uint32), - ('reserved3', p_uint32), - ('reserved4', p_uint32), - ('reserved5', p_uint32), - ('reserved6', p_uint32), + ("init_address", p_uint32), + ("init_module", p_uint32), + ("reserved1", p_uint32), + ("reserved2", p_uint32), + ("reserved3", p_uint32), + ("reserved4", p_uint32), + ("reserved5", p_uint32), + ("reserved6", p_uint32), ) def describe(self): s = {} - s['init_address'] = int(self.init_address) - s['init_module'] = int(self.init_module) - s['reserved1'] = int(self.reserved1) - s['reserved2'] = int(self.reserved2) - s['reserved3'] = int(self.reserved3) - s['reserved4'] = int(self.reserved4) - s['reserved5'] = int(self.reserved5) - s['reserved6'] = int(self.reserved6) + s["init_address"] = int(self.init_address) + s["init_module"] = int(self.init_module) + s["reserved1"] = int(self.reserved1) + s["reserved2"] = int(self.reserved2) + s["reserved3"] = int(self.reserved3) + s["reserved4"] = int(self.reserved4) + s["reserved5"] = int(self.reserved5) + s["reserved6"] = int(self.reserved6) return s class routines_command_64(Structure): _fields_ = ( - ('init_address', p_uint64), - ('init_module', p_uint64), - ('reserved1', p_uint64), - ('reserved2', p_uint64), - ('reserved3', p_uint64), - ('reserved4', p_uint64), - ('reserved5', p_uint64), - ('reserved6', p_uint64), + ("init_address", p_uint64), + ("init_module", p_uint64), + ("reserved1", p_uint64), + ("reserved2", p_uint64), + ("reserved3", p_uint64), + ("reserved4", p_uint64), + ("reserved5", p_uint64), + ("reserved6", p_uint64), ) def describe(self): s = {} - s['init_address'] = int(self.init_address) - s['init_module'] = int(self.init_module) - s['reserved1'] = int(self.reserved1) - s['reserved2'] = int(self.reserved2) - s['reserved3'] = int(self.reserved3) - s['reserved4'] = int(self.reserved4) - s['reserved5'] = int(self.reserved5) - s['reserved6'] = int(self.reserved6) + s["init_address"] = int(self.init_address) + s["init_module"] = int(self.init_module) + s["reserved1"] = int(self.reserved1) + s["reserved2"] = int(self.reserved2) + s["reserved3"] = int(self.reserved3) + s["reserved4"] = int(self.reserved4) + s["reserved5"] = int(self.reserved5) + s["reserved6"] = int(self.reserved6) return s class symtab_command(Structure): _fields_ = ( - ('symoff', p_uint32), - ('nsyms', p_uint32), - ('stroff', p_uint32), - ('strsize', p_uint32), + ("symoff", p_uint32), + ("nsyms", p_uint32), + ("stroff", p_uint32), + ("strsize", p_uint32), ) def describe(self): s = {} - s['symoff'] = int(self.symoff) - s['nsyms'] = int(self.nsyms) - s['stroff'] = int(self.stroff) - s['strsize'] = int(self.strsize) + s["symoff"] = int(self.symoff) + s["nsyms"] = int(self.nsyms) + s["stroff"] = int(self.stroff) + s["strsize"] = int(self.strsize) return s class dysymtab_command(Structure): _fields_ = ( - ('ilocalsym', p_uint32), - ('nlocalsym', p_uint32), - ('iextdefsym', p_uint32), - ('nextdefsym', p_uint32), - ('iundefsym', p_uint32), - ('nundefsym', p_uint32), - ('tocoff', p_uint32), - ('ntoc', p_uint32), - ('modtaboff', p_uint32), - ('nmodtab', p_uint32), - ('extrefsymoff', p_uint32), - ('nextrefsyms', p_uint32), - ('indirectsymoff', p_uint32), - ('nindirectsyms', p_uint32), - ('extreloff', p_uint32), - ('nextrel', p_uint32), - ('locreloff', p_uint32), - ('nlocrel', p_uint32), + ("ilocalsym", p_uint32), + ("nlocalsym", p_uint32), + ("iextdefsym", p_uint32), + ("nextdefsym", p_uint32), + ("iundefsym", p_uint32), + ("nundefsym", p_uint32), + ("tocoff", p_uint32), + ("ntoc", p_uint32), + ("modtaboff", p_uint32), + ("nmodtab", p_uint32), + ("extrefsymoff", p_uint32), + ("nextrefsyms", p_uint32), + ("indirectsymoff", p_uint32), + ("nindirectsyms", p_uint32), + ("extreloff", p_uint32), + ("nextrel", p_uint32), + ("locreloff", p_uint32), + ("nlocrel", p_uint32), ) def describe(self): dys = {} - dys['ilocalsym'] = int(self.ilocalsym) - dys['nlocalsym'] = int(self.nlocalsym) - dys['iextdefsym'] = int(self.iextdefsym) - dys['nextdefsym'] = int(self.nextdefsym) - dys['iundefsym'] = int(self.iundefsym) - dys['nundefsym'] = int(self.nundefsym) - dys['tocoff'] = int(self.tocoff) - dys['ntoc'] = int(self.ntoc) - dys['modtaboff'] = int(self.modtaboff) - dys['nmodtab'] = int(self.nmodtab) - dys['extrefsymoff'] = int(self.extrefsymoff) - dys['nextrefsyms'] = int(self.nextrefsyms) - dys['indirectsymoff'] = int(self.indirectsymoff) - dys['nindirectsyms'] = int(self.nindirectsyms) - dys['extreloff'] = int(self.extreloff) - dys['nextrel'] = int(self.nextrel) - dys['locreloff'] = int(self.locreloff) - dys['nlocrel'] = int(self.nlocrel) + dys["ilocalsym"] = int(self.ilocalsym) + dys["nlocalsym"] = int(self.nlocalsym) + dys["iextdefsym"] = int(self.iextdefsym) + dys["nextdefsym"] = int(self.nextdefsym) + dys["iundefsym"] = int(self.iundefsym) + dys["nundefsym"] = int(self.nundefsym) + dys["tocoff"] = int(self.tocoff) + dys["ntoc"] = int(self.ntoc) + dys["modtaboff"] = int(self.modtaboff) + dys["nmodtab"] = int(self.nmodtab) + dys["extrefsymoff"] = int(self.extrefsymoff) + dys["nextrefsyms"] = int(self.nextrefsyms) + dys["indirectsymoff"] = int(self.indirectsymoff) + dys["nindirectsyms"] = int(self.nindirectsyms) + dys["extreloff"] = int(self.extreloff) + dys["nextrel"] = int(self.nextrel) + dys["locreloff"] = int(self.locreloff) + dys["nlocrel"] = int(self.nlocrel) return dys @@ -1029,153 +1038,129 @@ INDIRECT_SYMBOL_ABS = 0x40000000 class dylib_table_of_contents(Structure): - _fields_ = ( - ('symbol_index', p_uint32), - ('module_index', p_uint32), - ) + _fields_ = (("symbol_index", p_uint32), ("module_index", p_uint32)) class dylib_module(Structure): _fields_ = ( - ('module_name', p_uint32), - ('iextdefsym', p_uint32), - ('nextdefsym', p_uint32), - ('irefsym', p_uint32), - ('nrefsym', p_uint32), - ('ilocalsym', p_uint32), - ('nlocalsym', p_uint32), - ('iextrel', p_uint32), - ('nextrel', p_uint32), - ('iinit_iterm', p_uint32), - ('ninit_nterm', p_uint32), - ('objc_module_info_addr', p_uint32), - ('objc_module_info_size', p_uint32), + ("module_name", p_uint32), + ("iextdefsym", p_uint32), + ("nextdefsym", p_uint32), + ("irefsym", p_uint32), + ("nrefsym", p_uint32), + ("ilocalsym", p_uint32), + ("nlocalsym", p_uint32), + ("iextrel", p_uint32), + ("nextrel", p_uint32), + ("iinit_iterm", p_uint32), + ("ninit_nterm", p_uint32), + ("objc_module_info_addr", p_uint32), + ("objc_module_info_size", p_uint32), ) class dylib_module_64(Structure): _fields_ = ( - ('module_name', p_uint32), - ('iextdefsym', p_uint32), - ('nextdefsym', p_uint32), - ('irefsym', p_uint32), - ('nrefsym', p_uint32), - ('ilocalsym', p_uint32), - ('nlocalsym', p_uint32), - ('iextrel', p_uint32), - ('nextrel', p_uint32), - ('iinit_iterm', p_uint32), - ('ninit_nterm', p_uint32), - ('objc_module_info_size', p_uint32), - ('objc_module_info_addr', p_uint64), + ("module_name", p_uint32), + ("iextdefsym", p_uint32), + ("nextdefsym", p_uint32), + ("irefsym", p_uint32), + ("nrefsym", p_uint32), + ("ilocalsym", p_uint32), + ("nlocalsym", p_uint32), + ("iextrel", p_uint32), + ("nextrel", p_uint32), + ("iinit_iterm", p_uint32), + ("ninit_nterm", p_uint32), + ("objc_module_info_size", p_uint32), + ("objc_module_info_addr", p_uint64), ) class dylib_reference(Structure): _fields_ = ( - # XXX - ick, fix - ('isym_flags', p_uint32), + ("isym_flags", p_uint32), # ('isym', p_uint8 * 3), # ('flags', p_uint8), ) class twolevel_hints_command(Structure): - _fields_ = ( - ('offset', p_uint32), - ('nhints', p_uint32), - ) + _fields_ = (("offset", p_uint32), ("nhints", p_uint32)) def describe(self): s = {} - s['offset'] = int(self.offset) - s['nhints'] = int(self.nhints) + s["offset"] = int(self.offset) + s["nhints"] = int(self.nhints) return s class twolevel_hint(Structure): _fields_ = ( - # XXX - ick, fix - ('isub_image_itoc', p_uint32), - # ('isub_image', p_uint8), - # ('itoc', p_uint8 * 3), + ("isub_image_itoc", p_uint32), + # ('isub_image', p_uint8), + # ('itoc', p_uint8 * 3), ) class prebind_cksum_command(Structure): - _fields_ = ( - ('cksum', p_uint32), - ) + _fields_ = (("cksum", p_uint32),) def describe(self): - return {'cksum': int(self.cksum)} + return {"cksum": int(self.cksum)} class symseg_command(Structure): - _fields_ = ( - ('offset', p_uint32), - ('size', p_uint32), - ) + _fields_ = (("offset", p_uint32), ("size", p_uint32)) def describe(self): s = {} - s['offset'] = int(self.offset) - s['size'] = int(self.size) + s["offset"] = int(self.offset) + s["size"] = int(self.size) class ident_command(Structure): - _fields_ = ( - ) + _fields_ = () def describe(self): return {} class fvmfile_command(Structure): - _fields_ = ( - ('name', lc_str), - ('header_addr', p_uint32), - ) + _fields_ = (("name", lc_str), ("header_addr", p_uint32)) def describe(self): - return {'header_addr': int(self.header_addr)} + return {"header_addr": int(self.header_addr)} -class uuid_command (Structure): - _fields_ = ( - ('uuid', p_str16), - ) +class uuid_command(Structure): + _fields_ = (("uuid", p_str16),) def describe(self): - return {'uuid': self.uuid.rstrip('\x00')} + return {"uuid": self.uuid.rstrip("\x00")} -class rpath_command (Structure): - _fields_ = ( - ('path', lc_str), - ) +class rpath_command(Structure): + _fields_ = (("path", lc_str),) def describe(self): return {} -class linkedit_data_command (Structure): - _fields_ = ( - ('dataoff', p_uint32), - ('datasize', p_uint32), - ) +class linkedit_data_command(Structure): + _fields_ = (("dataoff", p_uint32), ("datasize", p_uint32)) def describe(self): s = {} - s['dataoff'] = int(self.dataoff) - s['datasize'] = int(self.datasize) + s["dataoff"] = int(self.dataoff) + s["datasize"] = int(self.datasize) return s -class version_min_command (Structure): +class version_min_command(Structure): _fields_ = ( - ('version', p_uint32), # X.Y.Z is encoded in nibbles xxxx.yy.zz - ('sdk', p_uint32), + ("version", p_uint32), # X.Y.Z is encoded in nibbles xxxx.yy.zz + ("sdk", p_uint32), ) def describe(self): @@ -1192,63 +1177,50 @@ class version_min_command (Structure): s = s >> 8 s1 = s & 0xFFFF return { - 'version': str(int(v1)) + "." + str(int(v2)) + "." + str(int(v3)), - 'sdk': str(int(s1)) + "." + str(int(s2)) + "." + str(int(s3)) + "version": str(int(v1)) + "." + str(int(v2)) + "." + str(int(v3)), + "sdk": str(int(s1)) + "." + str(int(s2)) + "." + str(int(s3)), } -class source_version_command (Structure): - _fields_ = ( - ('version', p_uint64), - ) +class source_version_command(Structure): + _fields_ = (("version", p_uint64),) def describe(self): v = int(self.version) a = v >> 40 - b = (v >> 30) & 0x3ff - c = (v >> 20) & 0x3ff - d = (v >> 10) & 0x3ff - e = v & 0x3ff - r = str(a)+'.'+str(b)+'.'+str(c)+'.'+str(d)+'.'+str(e) - return {'version': r} + b = (v >> 30) & 0x3FF + c = (v >> 20) & 0x3FF + d = (v >> 10) & 0x3FF + e = v & 0x3FF + r = str(a) + "." + str(b) + "." + str(c) + "." + str(d) + "." + str(e) + return {"version": r} -class note_command (Structure): - _fields_ = ( - ('data_owner', p_str16), - ('offset', p_uint64), - ('size', p_uint64), - ) +class note_command(Structure): + _fields_ = (("data_owner", p_str16), ("offset", p_uint64), ("size", p_uint64)) -class build_version_command (Structure): +class build_version_command(Structure): _fields_ = ( - ('platform', p_uint32), - ('minos', p_uint32), - ('sdk', p_uint32), - ('ntools', p_uint32), + ("platform", p_uint32), + ("minos", p_uint32), + ("sdk", p_uint32), + ("ntools", p_uint32), ) - # XXX: Add computed field for accessing 'tools' array + def describe(self): + return {} -class build_tool_version (Structure): - _fields_ = ( - ('tool', p_uint32), - ('version', p_uint32), - ) +class build_tool_version(Structure): + _fields_ = (("tool", p_uint32), ("version", p_uint32)) -class data_in_code_entry (Structure): - _fields_ = ( - ('offset', p_uint32), - ('length', p_uint32), - ('kind', p_uint32), - ) +class data_in_code_entry(Structure): + _fields_ = (("offset", p_uint32), ("length", p_uint32), ("kind", p_uint32)) def describe(self): - return { - 'offset': self.offset, 'length': self.length, 'kind': self.kind} + return {"offset": self.offset, "length": self.length, "kind": self.kind} DICE_KIND_DATA = 0x0001 @@ -1258,197 +1230,209 @@ DICE_KIND_JUMP_TABLE32 = 0x0004 DICE_KIND_ABS_JUMP_TABLE32 = 0x0005 DATA_IN_CODE_KINDS = { - DICE_KIND_DATA: 'DICE_KIND_DATA', - DICE_KIND_JUMP_TABLE8: 'DICE_KIND_JUMP_TABLE8', - DICE_KIND_JUMP_TABLE16: 'DICE_KIND_JUMP_TABLE16', - DICE_KIND_JUMP_TABLE32: 'DICE_KIND_JUMP_TABLE32', - DICE_KIND_ABS_JUMP_TABLE32: 'DICE_KIND_ABS_JUMP_TABLE32', + DICE_KIND_DATA: "DICE_KIND_DATA", + DICE_KIND_JUMP_TABLE8: "DICE_KIND_JUMP_TABLE8", + DICE_KIND_JUMP_TABLE16: "DICE_KIND_JUMP_TABLE16", + DICE_KIND_JUMP_TABLE32: "DICE_KIND_JUMP_TABLE32", + DICE_KIND_ABS_JUMP_TABLE32: "DICE_KIND_ABS_JUMP_TABLE32", } -class tlv_descriptor (Structure): +class tlv_descriptor(Structure): _fields_ = ( - ('thunk', p_long), # Actually a pointer to a function - ('key', p_ulong), - ('offset', p_ulong), + ("thunk", p_long), # Actually a pointer to a function + ("key", p_ulong), + ("offset", p_ulong), ) def describe(self): - return {'thunk': self.thunk, 'key': self.key, 'offset': self.offset} + return {"thunk": self.thunk, "key": self.key, "offset": self.offset} -class encryption_info_command (Structure): - _fields_ = ( - ('cryptoff', p_uint32), - ('cryptsize', p_uint32), - ('cryptid', p_uint32), - ) +class encryption_info_command(Structure): + _fields_ = (("cryptoff", p_uint32), ("cryptsize", p_uint32), ("cryptid", p_uint32)) def describe(self): s = {} - s['cryptoff'] = int(self.cryptoff) - s['cryptsize'] = int(self.cryptsize) - s['cryptid'] = int(self.cryptid) + s["cryptoff"] = int(self.cryptoff) + s["cryptsize"] = int(self.cryptsize) + s["cryptid"] = int(self.cryptid) return s -class encryption_info_command_64 (Structure): +class encryption_info_command_64(Structure): _fields_ = ( - ('cryptoff', p_uint32), - ('cryptsize', p_uint32), - ('cryptid', p_uint32), - ('pad', p_uint32), + ("cryptoff", p_uint32), + ("cryptsize", p_uint32), + ("cryptid", p_uint32), + ("pad", p_uint32), ) def describe(self): s = {} - s['cryptoff'] = int(self.cryptoff) - s['cryptsize'] = int(self.cryptsize) - s['cryptid'] = int(self.cryptid) - s['pad'] = int(self.pad) + s["cryptoff"] = int(self.cryptoff) + s["cryptsize"] = int(self.cryptsize) + s["cryptid"] = int(self.cryptid) + s["pad"] = int(self.pad) return s -class dyld_info_command (Structure): +class dyld_info_command(Structure): _fields_ = ( - ('rebase_off', p_uint32), - ('rebase_size', p_uint32), - ('bind_off', p_uint32), - ('bind_size', p_uint32), - ('weak_bind_off', p_uint32), - ('weak_bind_size', p_uint32), - ('lazy_bind_off', p_uint32), - ('lazy_bind_size', p_uint32), - ('export_off', p_uint32), - ('export_size', p_uint32), + ("rebase_off", p_uint32), + ("rebase_size", p_uint32), + ("bind_off", p_uint32), + ("bind_size", p_uint32), + ("weak_bind_off", p_uint32), + ("weak_bind_size", p_uint32), + ("lazy_bind_off", p_uint32), + ("lazy_bind_size", p_uint32), + ("export_off", p_uint32), + ("export_size", p_uint32), ) def describe(self): dyld = {} - dyld['rebase_off'] = int(self.rebase_off) - dyld['rebase_size'] = int(self.rebase_size) - dyld['bind_off'] = int(self.bind_off) - dyld['bind_size'] = int(self.bind_size) - dyld['weak_bind_off'] = int(self.weak_bind_off) - dyld['weak_bind_size'] = int(self.weak_bind_size) - dyld['lazy_bind_off'] = int(self.lazy_bind_off) - dyld['lazy_bind_size'] = int(self.lazy_bind_size) - dyld['export_off'] = int(self.export_off) - dyld['export_size'] = int(self.export_size) + dyld["rebase_off"] = int(self.rebase_off) + dyld["rebase_size"] = int(self.rebase_size) + dyld["bind_off"] = int(self.bind_off) + dyld["bind_size"] = int(self.bind_size) + dyld["weak_bind_off"] = int(self.weak_bind_off) + dyld["weak_bind_size"] = int(self.weak_bind_size) + dyld["lazy_bind_off"] = int(self.lazy_bind_off) + dyld["lazy_bind_size"] = int(self.lazy_bind_size) + dyld["export_off"] = int(self.export_off) + dyld["export_size"] = int(self.export_size) return dyld -class linker_option_command (Structure): - _fields_ = ( - ('count', p_uint32), - ) +class linker_option_command(Structure): + _fields_ = (("count", p_uint32),) def describe(self): - return {'count': int(self.count)} + return {"count": int(self.count)} + + +class fileset_entry_command(Structure): + _fields_ = ( + ("vmaddr", p_uint64), + ("fileoff", p_uint64), + ("entry_id", lc_str), + ("reserved", p_uint32), + ) LC_REGISTRY = { - LC_SEGMENT: segment_command, - LC_IDFVMLIB: fvmlib_command, - LC_LOADFVMLIB: fvmlib_command, - LC_ID_DYLIB: dylib_command, - LC_LOAD_DYLIB: dylib_command, + LC_SEGMENT: segment_command, + LC_IDFVMLIB: fvmlib_command, + LC_LOADFVMLIB: fvmlib_command, + LC_ID_DYLIB: dylib_command, + LC_LOAD_DYLIB: dylib_command, LC_LOAD_WEAK_DYLIB: dylib_command, - LC_SUB_FRAMEWORK: sub_framework_command, - LC_SUB_CLIENT: sub_client_command, - LC_SUB_UMBRELLA: sub_umbrella_command, - LC_SUB_LIBRARY: sub_library_command, - LC_PREBOUND_DYLIB: prebound_dylib_command, - LC_ID_DYLINKER: dylinker_command, - LC_LOAD_DYLINKER: dylinker_command, - LC_THREAD: thread_command, - LC_UNIXTHREAD: thread_command, - LC_ROUTINES: routines_command, - LC_SYMTAB: symtab_command, - LC_DYSYMTAB: dysymtab_command, - LC_TWOLEVEL_HINTS: twolevel_hints_command, - LC_PREBIND_CKSUM: prebind_cksum_command, - LC_SYMSEG: symseg_command, - LC_IDENT: ident_command, - LC_FVMFILE: fvmfile_command, - LC_SEGMENT_64: segment_command_64, - LC_ROUTINES_64: routines_command_64, - LC_UUID: uuid_command, - LC_RPATH: rpath_command, - LC_CODE_SIGNATURE: linkedit_data_command, - LC_CODE_SEGMENT_SPLIT_INFO: linkedit_data_command, - LC_REEXPORT_DYLIB: dylib_command, + LC_SUB_FRAMEWORK: sub_framework_command, + LC_SUB_CLIENT: sub_client_command, + LC_SUB_UMBRELLA: sub_umbrella_command, + LC_SUB_LIBRARY: sub_library_command, + LC_PREBOUND_DYLIB: prebound_dylib_command, + LC_ID_DYLINKER: dylinker_command, + LC_LOAD_DYLINKER: dylinker_command, + LC_THREAD: thread_command, + LC_UNIXTHREAD: thread_command, + LC_ROUTINES: routines_command, + LC_SYMTAB: symtab_command, + LC_DYSYMTAB: dysymtab_command, + LC_TWOLEVEL_HINTS: twolevel_hints_command, + LC_PREBIND_CKSUM: prebind_cksum_command, + LC_SYMSEG: symseg_command, + LC_IDENT: ident_command, + LC_FVMFILE: fvmfile_command, + LC_SEGMENT_64: segment_command_64, + LC_ROUTINES_64: routines_command_64, + LC_UUID: uuid_command, + LC_RPATH: rpath_command, + LC_CODE_SIGNATURE: linkedit_data_command, + LC_CODE_SEGMENT_SPLIT_INFO: linkedit_data_command, + LC_REEXPORT_DYLIB: dylib_command, LC_LAZY_LOAD_DYLIB: dylib_command, LC_ENCRYPTION_INFO: encryption_info_command, - LC_DYLD_INFO: dyld_info_command, - LC_DYLD_INFO_ONLY: dyld_info_command, + LC_DYLD_INFO: dyld_info_command, + LC_DYLD_INFO_ONLY: dyld_info_command, LC_LOAD_UPWARD_DYLIB: dylib_command, LC_VERSION_MIN_MACOSX: version_min_command, LC_VERSION_MIN_IPHONEOS: version_min_command, - LC_FUNCTION_STARTS: linkedit_data_command, + LC_FUNCTION_STARTS: linkedit_data_command, LC_DYLD_ENVIRONMENT: dylinker_command, LC_MAIN: entry_point_command, LC_DATA_IN_CODE: linkedit_data_command, LC_SOURCE_VERSION: source_version_command, - LC_DYLIB_CODE_SIGN_DRS: linkedit_data_command, + LC_DYLIB_CODE_SIGN_DRS: linkedit_data_command, LC_ENCRYPTION_INFO_64: encryption_info_command_64, - LC_LINKER_OPTION: linker_option_command, - LC_LINKER_OPTIMIZATION_HINT: linkedit_data_command, + LC_LINKER_OPTION: linker_option_command, + LC_LINKER_OPTIMIZATION_HINT: linkedit_data_command, LC_VERSION_MIN_TVOS: version_min_command, LC_VERSION_MIN_WATCHOS: version_min_command, LC_NOTE: note_command, LC_BUILD_VERSION: build_version_command, + LC_DYLD_EXPORTS_TRIE: linkedit_data_command, + LC_DYLD_CHAINED_FIXUPS: linkedit_data_command, + LC_FILESET_ENTRY: fileset_entry_command, } LC_NAMES = { - LC_SEGMENT: 'LC_SEGMENT', - LC_IDFVMLIB: 'LC_IDFVMLIB', - LC_LOADFVMLIB: 'LC_LOADFVMLIB', - LC_ID_DYLIB: 'LC_ID_DYLIB', - LC_LOAD_DYLIB: 'LC_LOAD_DYLIB', - LC_LOAD_WEAK_DYLIB: 'LC_LOAD_WEAK_DYLIB', - LC_SUB_FRAMEWORK: 'LC_SUB_FRAMEWORK', - LC_SUB_CLIENT: 'LC_SUB_CLIENT', - LC_SUB_UMBRELLA: 'LC_SUB_UMBRELLA', - LC_SUB_LIBRARY: 'LC_SUB_LIBRARY', - LC_PREBOUND_DYLIB: 'LC_PREBOUND_DYLIB', - LC_ID_DYLINKER: 'LC_ID_DYLINKER', - LC_LOAD_DYLINKER: 'LC_LOAD_DYLINKER', - LC_THREAD: 'LC_THREAD', - LC_UNIXTHREAD: 'LC_UNIXTHREAD', - LC_ROUTINES: 'LC_ROUTINES', - LC_SYMTAB: 'LC_SYMTAB', - LC_DYSYMTAB: 'LC_DYSYMTAB', - LC_TWOLEVEL_HINTS: 'LC_TWOLEVEL_HINTS', - LC_PREBIND_CKSUM: 'LC_PREBIND_CKSUM', - LC_SYMSEG: 'LC_SYMSEG', - LC_IDENT: 'LC_IDENT', - LC_FVMFILE: 'LC_FVMFILE', - LC_SEGMENT_64: 'LC_SEGMENT_64', - LC_ROUTINES_64: 'LC_ROUTINES_64', - LC_UUID: 'LC_UUID', - LC_RPATH: 'LC_RPATH', - LC_CODE_SIGNATURE: 'LC_CODE_SIGNATURE', - LC_CODE_SEGMENT_SPLIT_INFO: 'LC_CODE_SEGMENT_SPLIT_INFO', - LC_REEXPORT_DYLIB: 'LC_REEXPORT_DYLIB', - LC_LAZY_LOAD_DYLIB: 'LC_LAZY_LOAD_DYLIB', - LC_ENCRYPTION_INFO: 'LC_ENCRYPTION_INFO', - LC_DYLD_INFO: 'LC_DYLD_INFO', - LC_DYLD_INFO_ONLY: 'LC_DYLD_INFO_ONLY', - LC_LOAD_UPWARD_DYLIB: 'LC_LOAD_UPWARD_DYLIB', - LC_VERSION_MIN_MACOSX: 'LC_VERSION_MIN_MACOSX', - LC_VERSION_MIN_IPHONEOS: 'LC_VERSION_MIN_IPHONEOS', - LC_FUNCTION_STARTS: 'LC_FUNCTION_STARTS', - LC_DYLD_ENVIRONMENT: 'LC_DYLD_ENVIRONMENT', - LC_MAIN: 'LC_MAIN', - LC_DATA_IN_CODE: 'LC_DATA_IN_CODE', - LC_SOURCE_VERSION: 'LC_SOURCE_VERSION', - LC_DYLIB_CODE_SIGN_DRS: 'LC_DYLIB_CODE_SIGN_DRS', - LC_LINKER_OPTIMIZATION_HINT: 'LC_LINKER_OPTIMIZATION_HINT', - LC_VERSION_MIN_TVOS: 'LC_VERSION_MIN_TVOS', - LC_VERSION_MIN_WATCHOS: 'LC_VERSION_MIN_WATCHOS', - LC_NOTE: 'LC_NOTE', - LC_BUILD_VERSION: 'LC_BUILD_VERSION', + LC_SEGMENT: "LC_SEGMENT", + LC_IDFVMLIB: "LC_IDFVMLIB", + LC_LOADFVMLIB: "LC_LOADFVMLIB", + LC_ID_DYLIB: "LC_ID_DYLIB", + LC_LOAD_DYLIB: "LC_LOAD_DYLIB", + LC_LOAD_WEAK_DYLIB: "LC_LOAD_WEAK_DYLIB", + LC_SUB_FRAMEWORK: "LC_SUB_FRAMEWORK", + LC_SUB_CLIENT: "LC_SUB_CLIENT", + LC_SUB_UMBRELLA: "LC_SUB_UMBRELLA", + LC_SUB_LIBRARY: "LC_SUB_LIBRARY", + LC_PREBOUND_DYLIB: "LC_PREBOUND_DYLIB", + LC_ID_DYLINKER: "LC_ID_DYLINKER", + LC_LOAD_DYLINKER: "LC_LOAD_DYLINKER", + LC_THREAD: "LC_THREAD", + LC_UNIXTHREAD: "LC_UNIXTHREAD", + LC_ROUTINES: "LC_ROUTINES", + LC_SYMTAB: "LC_SYMTAB", + LC_DYSYMTAB: "LC_DYSYMTAB", + LC_TWOLEVEL_HINTS: "LC_TWOLEVEL_HINTS", + LC_PREBIND_CKSUM: "LC_PREBIND_CKSUM", + LC_SYMSEG: "LC_SYMSEG", + LC_IDENT: "LC_IDENT", + LC_FVMFILE: "LC_FVMFILE", + LC_SEGMENT_64: "LC_SEGMENT_64", + LC_ROUTINES_64: "LC_ROUTINES_64", + LC_UUID: "LC_UUID", + LC_RPATH: "LC_RPATH", + LC_CODE_SIGNATURE: "LC_CODE_SIGNATURE", + LC_CODE_SEGMENT_SPLIT_INFO: "LC_CODE_SEGMENT_SPLIT_INFO", + LC_REEXPORT_DYLIB: "LC_REEXPORT_DYLIB", + LC_LAZY_LOAD_DYLIB: "LC_LAZY_LOAD_DYLIB", + LC_ENCRYPTION_INFO: "LC_ENCRYPTION_INFO", + LC_DYLD_INFO: "LC_DYLD_INFO", + LC_DYLD_INFO_ONLY: "LC_DYLD_INFO_ONLY", + LC_LOAD_UPWARD_DYLIB: "LC_LOAD_UPWARD_DYLIB", + LC_VERSION_MIN_MACOSX: "LC_VERSION_MIN_MACOSX", + LC_VERSION_MIN_IPHONEOS: "LC_VERSION_MIN_IPHONEOS", + LC_FUNCTION_STARTS: "LC_FUNCTION_STARTS", + LC_DYLD_ENVIRONMENT: "LC_DYLD_ENVIRONMENT", + LC_MAIN: "LC_MAIN", + LC_DATA_IN_CODE: "LC_DATA_IN_CODE", + LC_SOURCE_VERSION: "LC_SOURCE_VERSION", + LC_DYLIB_CODE_SIGN_DRS: "LC_DYLIB_CODE_SIGN_DRS", + LC_LINKER_OPTIMIZATION_HINT: "LC_LINKER_OPTIMIZATION_HINT", + LC_VERSION_MIN_TVOS: "LC_VERSION_MIN_TVOS", + LC_VERSION_MIN_WATCHOS: "LC_VERSION_MIN_WATCHOS", + LC_NOTE: "LC_NOTE", + LC_BUILD_VERSION: "LC_BUILD_VERSION", + LC_DYLD_EXPORTS_TRIE: "LC_DYLD_EXPORTS_TRIE", + LC_DYLD_CHAINED_FIXUPS: "LC_DYLD_CHAINED_FIXUPS", + LC_ENCRYPTION_INFO_64: "LC_ENCRYPTION_INFO_64", + LC_LINKER_OPTION: "LC_LINKER_OPTION", + LC_PREPAGE: "LC_PREPAGE", + LC_FILESET_ENTRY: "LC_FILESET_ENTRY", } @@ -1459,62 +1443,55 @@ class n_un(p_int32): class nlist(Structure): _fields_ = ( - ('n_un', n_un), - ('n_type', p_uint8), - ('n_sect', p_uint8), - ('n_desc', p_short), - ('n_value', p_uint32), + ("n_un", n_un), + ("n_type", p_uint8), + ("n_sect", p_uint8), + ("n_desc", p_short), + ("n_value", p_uint32), ) class nlist_64(Structure): _fields_ = [ - ('n_un', n_un), - ('n_type', p_uint8), - ('n_sect', p_uint8), - ('n_desc', p_short), - ('n_value', p_int64), + ("n_un", n_un), + ("n_type", p_uint8), + ("n_sect", p_uint8), + ("n_desc", p_short), + ("n_value", p_int64), ] -N_STAB = 0xe0 +N_STAB = 0xE0 N_PEXT = 0x10 -N_TYPE = 0x0e +N_TYPE = 0x0E N_EXT = 0x01 N_UNDF = 0x0 N_ABS = 0x2 -N_SECT = 0xe -N_PBUD = 0xc -N_INDR = 0xa +N_SECT = 0xE +N_PBUD = 0xC +N_INDR = 0xA NO_SECT = 0 MAX_SECT = 255 class relocation_info(Structure): - # XXX: Need to add code for decoding the bitfield! - _fields_ = ( - ('r_address', p_uint32), - ('_r_bitfield', p_uint32), - ) + _fields_ = (("r_address", p_uint32), ("_r_bitfield", p_uint32)) def _describe(self): - return ( - ('r_address', self.r_address), - ('_r_bitfield', self._r_bitfield), - ) + return (("r_address", self.r_address), ("_r_bitfield", self._r_bitfield)) def GET_COMM_ALIGN(n_desc): - return (n_desc >> 8) & 0x0f + return (n_desc >> 8) & 0x0F def SET_COMM_ALIGN(n_desc, align): - return (n_desc & 0xf0ff) | ((align & 0x0f) << 8) + return (n_desc & 0xF0FF) | ((align & 0x0F) << 8) -REFERENCE_TYPE = 0xf +REFERENCE_TYPE = 0xF REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0 REFERENCE_FLAG_UNDEFINED_LAZY = 1 REFERENCE_FLAG_DEFINED = 2 @@ -1526,17 +1503,17 @@ REFERENCED_DYNAMICALLY = 0x0010 def GET_LIBRARY_ORDINAL(n_desc): - return (((n_desc) >> 8) & 0xff) + return ((n_desc) >> 8) & 0xFF def SET_LIBRARY_ORDINAL(n_desc, ordinal): - return (((n_desc) & 0x00ff) | (((ordinal & 0xff) << 8))) + return ((n_desc) & 0x00FF) | (((ordinal & 0xFF) << 8)) SELF_LIBRARY_ORDINAL = 0x0 -MAX_LIBRARY_ORDINAL = 0xfd -DYNAMIC_LOOKUP_ORDINAL = 0xfe -EXECUTABLE_ORDINAL = 0xff +MAX_LIBRARY_ORDINAL = 0xFD +DYNAMIC_LOOKUP_ORDINAL = 0xFE +EXECUTABLE_ORDINAL = 0xFF N_NO_DEAD_STRIP = 0x0020 N_DESC_DISCARDED = 0x0020 @@ -1548,89 +1525,86 @@ N_SYMBOL_RESOLVER = 0x0100 N_ALT_ENTRY = 0x0200 # /usr/include/mach-o/fat.h -FAT_MAGIC = 0xcafebabe -FAT_CIGAM = 0xbebafeca -FAT_MAGIC_64 = 0xcafebabf -FAT_CIGAM_64 = 0xbfbafeca +FAT_MAGIC = 0xCAFEBABE +FAT_CIGAM = 0xBEBAFECA +FAT_MAGIC_64 = 0xCAFEBABF +FAT_CIGAM_64 = 0xBFBAFECA class fat_header(Structure): - _fields_ = ( - ('magic', p_uint32), - ('nfat_arch', p_uint32), - ) + _fields_ = (("magic", p_uint32), ("nfat_arch", p_uint32)) class fat_arch(Structure): _fields_ = ( - ('cputype', cpu_type_t), - ('cpusubtype', cpu_subtype_t), - ('offset', p_uint32), - ('size', p_uint32), - ('align', p_uint32), + ("cputype", cpu_type_t), + ("cpusubtype", cpu_subtype_t), + ("offset", p_uint32), + ("size", p_uint32), + ("align", p_uint32), ) class fat_arch64(Structure): _fields_ = ( - ('cputype', cpu_type_t), - ('cpusubtype', cpu_subtype_t), - ('offset', p_uint64), - ('size', p_uint64), - ('align', p_uint32), - ('reserved', p_uint32), + ("cputype", cpu_type_t), + ("cpusubtype", cpu_subtype_t), + ("offset", p_uint64), + ("size", p_uint64), + ("align", p_uint32), + ("reserved", p_uint32), ) -REBASE_TYPE_POINTER = 1 # noqa: E221 -REBASE_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 -REBASE_TYPE_TEXT_PCREL32 = 3 # noqa: E221 - -REBASE_OPCODE_MASK = 0xF0 # noqa: E221 -REBASE_IMMEDIATE_MASK = 0x0F # noqa: E221 -REBASE_OPCODE_DONE = 0x00 # noqa: E221 -REBASE_OPCODE_SET_TYPE_IMM = 0x10 # noqa: E221 -REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20 # noqa: E221 -REBASE_OPCODE_ADD_ADDR_ULEB = 0x30 # noqa: E221 -REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40 # noqa: E221 -REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50 # noqa: E221 -REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60 # noqa: E221 -REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70 # noqa: E221 -REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80 # noqa: E221 - -BIND_TYPE_POINTER = 1 # noqa: E221 -BIND_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 -BIND_TYPE_TEXT_PCREL32 = 3 # noqa: E221 - -BIND_SPECIAL_DYLIB_SELF = 0 # noqa: E221 -BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1 # noqa: E221 -BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2 # noqa: E221 - -BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1 # noqa: E221 -BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8 # noqa: E221 - -BIND_OPCODE_MASK = 0xF0 # noqa: E221 -BIND_IMMEDIATE_MASK = 0x0F # noqa: E221 -BIND_OPCODE_DONE = 0x00 # noqa: E221 -BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10 # noqa: E221 -BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20 # noqa: E221 -BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30 # noqa: E221 -BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40 # noqa: E221 -BIND_OPCODE_SET_TYPE_IMM = 0x50 # noqa: E221 -BIND_OPCODE_SET_ADDEND_SLEB = 0x60 # noqa: E221 -BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70 # noqa: E221 -BIND_OPCODE_ADD_ADDR_ULEB = 0x80 # noqa: E221 -BIND_OPCODE_DO_BIND = 0x90 # noqa: E221 -BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0 # noqa: E221 -BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0 # noqa: E221 -BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0 # noqa: E221 - -EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03 # noqa: E221 -EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00 # noqa: E221 -EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01 # noqa: E221 -EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04 # noqa: E221 -EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08 # noqa: E221 -EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10 # noqa: E221 +REBASE_TYPE_POINTER = 1 # noqa: E221 +REBASE_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 +REBASE_TYPE_TEXT_PCREL32 = 3 # noqa: E221 + +REBASE_OPCODE_MASK = 0xF0 # noqa: E221 +REBASE_IMMEDIATE_MASK = 0x0F # noqa: E221 +REBASE_OPCODE_DONE = 0x00 # noqa: E221 +REBASE_OPCODE_SET_TYPE_IMM = 0x10 # noqa: E221 +REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20 # noqa: E221 +REBASE_OPCODE_ADD_ADDR_ULEB = 0x30 # noqa: E221 +REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40 # noqa: E221 +REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80 # noqa: E221 + +BIND_TYPE_POINTER = 1 # noqa: E221 +BIND_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 +BIND_TYPE_TEXT_PCREL32 = 3 # noqa: E221 + +BIND_SPECIAL_DYLIB_SELF = 0 # noqa: E221 +BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1 # noqa: E221 +BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2 # noqa: E221 + +BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1 # noqa: E221 +BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8 # noqa: E221 + +BIND_OPCODE_MASK = 0xF0 # noqa: E221 +BIND_IMMEDIATE_MASK = 0x0F # noqa: E221 +BIND_OPCODE_DONE = 0x00 # noqa: E221 +BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10 # noqa: E221 +BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20 # noqa: E221 +BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30 # noqa: E221 +BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40 # noqa: E221 +BIND_OPCODE_SET_TYPE_IMM = 0x50 # noqa: E221 +BIND_OPCODE_SET_ADDEND_SLEB = 0x60 # noqa: E221 +BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70 # noqa: E221 +BIND_OPCODE_ADD_ADDR_ULEB = 0x80 # noqa: E221 +BIND_OPCODE_DO_BIND = 0x90 # noqa: E221 +BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0 # noqa: E221 +BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0 # noqa: E221 +BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0 # noqa: E221 + +EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03 # noqa: E221 +EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00 # noqa: E221 +EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01 # noqa: E221 +EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04 # noqa: E221 +EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08 # noqa: E221 +EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10 # noqa: E221 PLATFORM_MACOS = 1 PLATFORM_IOS = 2 @@ -1638,28 +1612,25 @@ PLATFORM_TVOS = 3 PLATFORM_WATCHOS = 4 PLATFORM_BRIDGEOS = 5 PLATFORM_IOSMAC = 6 +PLATFORM_MACCATALYST = 6 PLATFORM_IOSSIMULATOR = 7 PLATFORM_TVOSSIMULATOR = 8 PLATFORM_WATCHOSSIMULATOR = 9 PLATFORM_NAMES = { - PLATFORM_MACOS: 'macOS', - PLATFORM_IOS: 'iOS', - PLATFORM_TVOS: 'tvOS', - PLATFORM_WATCHOS: 'watchOS', - PLATFORM_BRIDGEOS: 'bridgeOS', - PLATFORM_IOSMAC: 'ios-on-mac', - PLATFORM_IOSSIMULATOR: 'iOS simulator', - PLATFORM_TVOSSIMULATOR: 'tvOS simulator', - PLATFORM_WATCHOSSIMULATOR: 'watchOS simulator', + PLATFORM_MACOS: "macOS", + PLATFORM_IOS: "iOS", + PLATFORM_TVOS: "tvOS", + PLATFORM_WATCHOS: "watchOS", + PLATFORM_BRIDGEOS: "bridgeOS", + PLATFORM_MACCATALYST: "catalyst", + PLATFORM_IOSSIMULATOR: "iOS simulator", + PLATFORM_TVOSSIMULATOR: "tvOS simulator", + PLATFORM_WATCHOSSIMULATOR: "watchOS simulator", } TOOL_CLANG = 1 TOOL_SWIFT = 2 TOOL_LD = 3 -TOOL_NAMES = { - TOOL_CLANG: 'clang', - TOOL_SWIFT: 'swift', - TOOL_LD: 'ld', -} +TOOL_NAMES = {TOOL_CLANG: "clang", TOOL_SWIFT: "swift", TOOL_LD: "ld"} diff --git a/lib/spack/external/macholib/macho_dump.py b/lib/spack/external/macholib/macho_dump.py index a30c2b92f8..bca5d777ae 100644 --- a/lib/spack/external/macholib/macho_dump.py +++ b/lib/spack/external/macholib/macho_dump.py @@ -5,15 +5,14 @@ from __future__ import print_function import sys from macholib._cmdline import main as _main +from macholib.mach_o import CPU_TYPE_NAMES, MH_CIGAM_64, MH_MAGIC_64, get_cpu_subtype from macholib.MachO import MachO -from macholib.mach_o import get_cpu_subtype, CPU_TYPE_NAMES -from macholib.mach_o import MH_CIGAM_64, MH_MAGIC_64 ARCH_MAP = { - ('<', '64-bit'): 'x86_64', - ('<', '32-bit'): 'i386', - ('>', '64-bit'): 'ppc64', - ('>', '32-bit'): 'ppc', + ("<", "64-bit"): "x86_64", + ("<", "32-bit"): "i386", + (">", "64-bit"): "ppc64", + (">", "32-bit"): "ppc", } @@ -24,34 +23,34 @@ def print_file(fp, path): seen = set() if header.MH_MAGIC == MH_MAGIC_64 or header.MH_MAGIC == MH_CIGAM_64: - sz = '64-bit' + sz = "64-bit" else: - sz = '32-bit' + sz = "32-bit" - arch = CPU_TYPE_NAMES.get( - header.header.cputype, header.header.cputype) + arch = CPU_TYPE_NAMES.get(header.header.cputype, header.header.cputype) - subarch = get_cpu_subtype( - header.header.cputype, header.header.cpusubtype) + subarch = get_cpu_subtype(header.header.cputype, header.header.cpusubtype) - print(' [%s endian=%r size=%r arch=%r subarch=%r]' % ( - header.__class__.__name__, header.endian, sz, arch, subarch), - file=fp) - for idx, name, other in header.walkRelocatables(): + print( + " [%s endian=%r size=%r arch=%r subarch=%r]" + % (header.__class__.__name__, header.endian, sz, arch, subarch), + file=fp, + ) + for _idx, _name, other in header.walkRelocatables(): if other not in seen: seen.add(other) - print('\t' + other, file=fp) - print('', file=fp) + print("\t" + other, file=fp) + print("", file=fp) def main(): print( - "WARNING: 'macho_dump' is deprecated, use 'python -mmacholib dump' " - "instead") + "WARNING: 'macho_dump' is deprecated, use 'python -mmacholib dump' " "instead" + ) _main(print_file) -if __name__ == '__main__': +if __name__ == "__main__": try: sys.exit(main()) except KeyboardInterrupt: diff --git a/lib/spack/external/macholib/macho_find.py b/lib/spack/external/macholib/macho_find.py index 8f8243e6db..a963c36dcc 100644 --- a/lib/spack/external/macholib/macho_find.py +++ b/lib/spack/external/macholib/macho_find.py @@ -1,5 +1,6 @@ #!/usr/bin/env python from __future__ import print_function + from macholib._cmdline import main as _main @@ -9,12 +10,12 @@ def print_file(fp, path): def main(): print( - "WARNING: 'macho_find' is deprecated, " - "use 'python -mmacholib dump' instead") + "WARNING: 'macho_find' is deprecated, " "use 'python -mmacholib dump' instead" + ) _main(print_file) -if __name__ == '__main__': +if __name__ == "__main__": try: main() except KeyboardInterrupt: diff --git a/lib/spack/external/macholib/macho_standalone.py b/lib/spack/external/macholib/macho_standalone.py index f9ce91e9bf..0bb29e802f 100644 --- a/lib/spack/external/macholib/macho_standalone.py +++ b/lib/spack/external/macholib/macho_standalone.py @@ -8,10 +8,8 @@ from macholib.util import strip_files def standaloneApp(path): - if not (os.path.isdir(path) and os.path.exists( - os.path.join(path, 'Contents'))): - print( - '%s: %s does not look like an app bundle' % (sys.argv[0], path)) + if not (os.path.isdir(path) and os.path.exists(os.path.join(path, "Contents"))): + print("%s: %s does not look like an app bundle" % (sys.argv[0], path)) sys.exit(1) files = MachOStandalone(path).run() strip_files(files) @@ -20,12 +18,13 @@ def standaloneApp(path): def main(): print( "WARNING: 'macho_standalone' is deprecated, use " - "'python -mmacholib standalone' instead") + "'python -mmacholib standalone' instead" + ) if not sys.argv[1:]: - raise SystemExit('usage: %s [appbundle ...]' % (sys.argv[0],)) + raise SystemExit("usage: %s [appbundle ...]" % (sys.argv[0],)) for fn in sys.argv[1:]: standaloneApp(fn) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/lib/spack/external/macholib/ptypes.py b/lib/spack/external/macholib/ptypes.py index a5643696b6..248b5cb2a3 100644 --- a/lib/spack/external/macholib/ptypes.py +++ b/lib/spack/external/macholib/ptypes.py @@ -4,12 +4,12 @@ converted to a binary format as used in MachO headers. """ import struct import sys +from itertools import chain, starmap try: - from itertools import izip, imap + from itertools import imap, izip except ImportError: izip, imap = zip, map -from itertools import chain, starmap __all__ = """ sizeof @@ -44,7 +44,7 @@ def sizeof(s): """ Return the size of an object when packed """ - if hasattr(s, '_size_'): + if hasattr(s, "_size_"): return s._size_ elif isinstance(s, bytes): @@ -58,14 +58,15 @@ class MetaPackable(type): Fixed size struct.unpack-able types use from_tuple as their designated initializer """ + def from_mmap(cls, mm, ptr, **kw): - return cls.from_str(mm[ptr:ptr+cls._size_], **kw) + return cls.from_str(mm[ptr : ptr + cls._size_], **kw) # noqa: E203 def from_fileobj(cls, f, **kw): return cls.from_str(f.read(cls._size_), **kw) def from_str(cls, s, **kw): - endian = kw.get('_endian_', cls._endian_) + endian = kw.get("_endian_", cls._endian_) return cls.from_tuple(struct.unpack(endian + cls._format_, s), **kw) def from_tuple(cls, tpl, **kw): @@ -73,7 +74,7 @@ class MetaPackable(type): class BasePackable(object): - _endian_ = '>' + _endian_ = ">" def to_str(self): raise NotImplementedError @@ -82,7 +83,7 @@ class BasePackable(object): f.write(self.to_str()) def to_mmap(self, mm, ptr): - mm[ptr:ptr+self._size_] = self.to_str() + mm[ptr : ptr + self._size_] = self.to_str() # noqa: E203 # This defines a class with a custom metaclass, we'd normally @@ -92,9 +93,10 @@ class BasePackable(object): def _make(): def to_str(self): cls = type(self) - endian = getattr(self, '_endian_', cls._endian_) + endian = getattr(self, "_endian_", cls._endian_) return struct.pack(endian + cls._format_, self) - return MetaPackable("Packable", (BasePackable,), {'to_str': to_str}) + + return MetaPackable("Packable", (BasePackable,), {"to_str": to_str}) Packable = _make() @@ -109,8 +111,8 @@ def pypackable(name, pytype, format): size, items = _formatinfo(format) def __new__(cls, *args, **kwds): - if '_endian_' in kwds: - _endian_ = kwds.pop('_endian_') + if "_endian_" in kwds: + _endian_ = kwds.pop("_endian_") else: _endian_ = cls._endian_ @@ -118,12 +120,11 @@ def pypackable(name, pytype, format): result._endian_ = _endian_ return result - return type(Packable)(name, (pytype, Packable), { - '_format_': format, - '_size_': size, - '_items_': items, - '__new__': __new__, - }) + return type(Packable)( + name, + (pytype, Packable), + {"_format_": format, "_size_": size, "_items_": items, "__new__": __new__}, + ) def _formatinfo(format): @@ -131,7 +132,7 @@ def _formatinfo(format): Calculate the size and number of items in a struct format. """ size = struct.calcsize(format) - return size, len(struct.unpack(format, b'\x00' * size)) + return size, len(struct.unpack(format, b"\x00" * size)) class MetaStructure(MetaPackable): @@ -142,17 +143,17 @@ class MetaStructure(MetaPackable): we can do a bunch of calculations up front and pack or unpack the whole thing in one struct call. """ + def __new__(cls, clsname, bases, dct): - fields = dct['_fields_'] + fields = dct["_fields_"] names = [] types = [] structmarks = [] - format = '' + format = "" items = 0 size = 0 def struct_property(name, typ): - def _get(self): return self._objects_[name] @@ -169,16 +170,16 @@ class MetaStructure(MetaPackable): types.append(typ) format += typ._format_ size += typ._size_ - if (typ._items_ > 1): + if typ._items_ > 1: structmarks.append((items, typ._items_, typ)) items += typ._items_ - dct['_structmarks_'] = structmarks - dct['_names_'] = names - dct['_types_'] = types - dct['_size_'] = size - dct['_items_'] = items - dct['_format_'] = format + dct["_structmarks_"] = structmarks + dct["_names_"] = names + dct["_types_"] = types + dct["_size_"] = size + dct["_items_"] = items + dct["_format_"] = format return super(MetaStructure, cls).__new__(cls, clsname, bases, dct) def from_tuple(cls, tpl, **kw): @@ -196,7 +197,7 @@ class MetaStructure(MetaPackable): # See metaclass discussion earlier in this file def _make(): class_dict = {} - class_dict['_fields_'] = () + class_dict["_fields_"] = () def as_method(function): class_dict[function.__name__] = function @@ -219,7 +220,7 @@ def _make(): @as_method def _get_packables(self): for obj in imap(self._objects_.__getitem__, self._names_): - if hasattr(obj, '_get_packables'): + if hasattr(obj, "_get_packables"): for obj in obj._get_packables(): yield obj @@ -228,18 +229,19 @@ def _make(): @as_method def to_str(self): - return struct.pack( - self._endian_ + self._format_, *self._get_packables()) + return struct.pack(self._endian_ + self._format_, *self._get_packables()) @as_method def __cmp__(self, other): if type(other) is not type(self): raise TypeError( - 'Cannot compare objects of type %r to objects of type %r' % ( - type(other), type(self))) + "Cannot compare objects of type %r to objects of type %r" + % (type(other), type(self)) + ) if sys.version_info[0] == 2: _cmp = cmp # noqa: F821 else: + def _cmp(a, b): if a < b: return -1 @@ -251,7 +253,8 @@ def _make(): raise TypeError() for cmpval in starmap( - _cmp, izip(self._get_packables(), other._get_packables())): + _cmp, izip(self._get_packables(), other._get_packables()) + ): if cmpval != 0: return cmpval return 0 @@ -289,12 +292,12 @@ def _make(): @as_method def __repr__(self): result = [] - result.append('<') + result.append("<") result.append(type(self).__name__) for nm in self._names_: - result.append(' %s=%r' % (nm, getattr(self, nm))) - result.append('>') - return ''.join(result) + result.append(" %s=%r" % (nm, getattr(self, nm))) + result.append(">") + return "".join(result) return MetaStructure("Structure", (BasePackable,), class_dict) @@ -308,17 +311,17 @@ except NameError: long = int # export common packables with predictable names -p_char = pypackable('p_char', bytes, 'c') -p_int8 = pypackable('p_int8', int, 'b') -p_uint8 = pypackable('p_uint8', int, 'B') -p_int16 = pypackable('p_int16', int, 'h') -p_uint16 = pypackable('p_uint16', int, 'H') -p_int32 = pypackable('p_int32', int, 'i') -p_uint32 = pypackable('p_uint32', long, 'I') -p_int64 = pypackable('p_int64', long, 'q') -p_uint64 = pypackable('p_uint64', long, 'Q') -p_float = pypackable('p_float', float, 'f') -p_double = pypackable('p_double', float, 'd') +p_char = pypackable("p_char", bytes, "c") +p_int8 = pypackable("p_int8", int, "b") +p_uint8 = pypackable("p_uint8", int, "B") +p_int16 = pypackable("p_int16", int, "h") +p_uint16 = pypackable("p_uint16", int, "H") +p_int32 = pypackable("p_int32", int, "i") +p_uint32 = pypackable("p_uint32", long, "I") +p_int64 = pypackable("p_int64", long, "q") +p_uint64 = pypackable("p_uint64", long, "Q") +p_float = pypackable("p_float", float, "f") +p_double = pypackable("p_double", float, "d") # Deprecated names, need trick to emit deprecation warning. p_byte = p_int8 diff --git a/lib/spack/external/macholib/util.py b/lib/spack/external/macholib/util.py index 99b682a27f..d5ab33544a 100644 --- a/lib/spack/external/macholib/util.py +++ b/lib/spack/external/macholib/util.py @@ -1,18 +1,18 @@ import os -import sys +import shutil import stat import struct -import shutil +import sys from macholib import mach_o MAGIC = [ - struct.pack('!L', getattr(mach_o, 'MH_' + _)) - for _ in ['MAGIC', 'CIGAM', 'MAGIC_64', 'CIGAM_64'] + struct.pack("!L", getattr(mach_o, "MH_" + _)) + for _ in ["MAGIC", "CIGAM", "MAGIC_64", "CIGAM_64"] ] -FAT_MAGIC_BYTES = struct.pack('!L', mach_o.FAT_MAGIC) +FAT_MAGIC_BYTES = struct.pack("!L", mach_o.FAT_MAGIC) MAGIC_LEN = 4 -STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-'] +STRIPCMD = ["/usr/bin/strip", "-x", "-S", "-"] try: unicode @@ -20,7 +20,7 @@ except NameError: unicode = str -def fsencoding(s, encoding=sys.getfilesystemencoding()): +def fsencoding(s, encoding=sys.getfilesystemencoding()): # noqa: M511,B008 """ Ensure the given argument is in filesystem encoding (not unicode) """ @@ -66,16 +66,17 @@ class fileview(object): self._end = start + size def __repr__(self): - return '' % ( - self._start, self._end, self._fileobj) + return "" % (self._start, self._end, self._fileobj) def tell(self): return self._fileobj.tell() - self._start def _checkwindow(self, seekto, op): if not (self._start <= seekto <= self._end): - raise IOError("%s to offset %d is outside window [%d, %d]" % ( - op, seekto, self._start, self._end)) + raise IOError( + "%s to offset %d is outside window [%d, %d]" + % (op, seekto, self._start, self._end) + ) def seek(self, offset, whence=0): seekto = offset @@ -87,21 +88,22 @@ class fileview(object): seekto += self._end else: raise IOError("Invalid whence argument to seek: %r" % (whence,)) - self._checkwindow(seekto, 'seek') + self._checkwindow(seekto, "seek") self._fileobj.seek(seekto) def write(self, bytes): here = self._fileobj.tell() - self._checkwindow(here, 'write') - self._checkwindow(here + len(bytes), 'write') + self._checkwindow(here, "write") + self._checkwindow(here + len(bytes), "write") self._fileobj.write(bytes) def read(self, size=sys.maxsize): if size < 0: raise ValueError( - "Invalid size %s while reading from %s", size, self._fileobj) + "Invalid size %s while reading from %s", size, self._fileobj + ) here = self._fileobj.tell() - self._checkwindow(here, 'read') + self._checkwindow(here, "read") bytes = min(size, self._end - here) return self._fileobj.read(bytes) @@ -110,8 +112,7 @@ def mergecopy(src, dest): """ copy2, but only if the destination isn't up to date """ - if os.path.exists(dest) and \ - os.stat(dest).st_mtime >= os.stat(src).st_mtime: + if os.path.exists(dest) and os.stat(dest).st_mtime >= os.stat(src).st_mtime: return copy2(src, dest) @@ -138,13 +139,16 @@ def mergetree(src, dst, condition=None, copyfn=mergecopy, srcbase=None): continue try: if os.path.islink(srcname): - # XXX: This is naive at best, should check srcbase(?) realsrc = os.readlink(srcname) os.symlink(realsrc, dstname) elif os.path.isdir(srcname): mergetree( - srcname, dstname, - condition=condition, copyfn=copyfn, srcbase=srcbase) + srcname, + dstname, + condition=condition, + copyfn=copyfn, + srcbase=srcbase, + ) else: copyfn(srcname, dstname) except (IOError, os.error) as why: @@ -158,10 +162,10 @@ def sdk_normalize(filename): Normalize a path to strip out the SDK portion, normally so that it can be decided whether it is in a system path or not. """ - if filename.startswith('/Developer/SDKs/'): - pathcomp = filename.split('/') + if filename.startswith("/Developer/SDKs/"): + pathcomp = filename.split("/") del pathcomp[1:4] - filename = '/'.join(pathcomp) + filename = "/".join(pathcomp) return filename @@ -173,9 +177,9 @@ def in_system_path(filename): Return True if the file is in a system path """ fn = sdk_normalize(os.path.realpath(filename)) - if fn.startswith('/usr/local/'): + if fn.startswith("/usr/local/"): return False - elif fn.startswith('/System/') or fn.startswith('/usr/'): + elif fn.startswith("/System/") or fn.startswith("/usr/"): if fn in NOT_SYSTEM_FILES: return False return True @@ -187,7 +191,7 @@ def has_filename_filter(module): """ Return False if the module does not have a filename attribute """ - return getattr(module, 'filename', None) is not None + return getattr(module, "filename", None) is not None def get_magic(): @@ -204,16 +208,16 @@ def is_platform_file(path): if not os.path.exists(path) or os.path.islink(path): return False # If the header is fat, we need to read into the first arch - with open(path, 'rb') as fileobj: + with open(path, "rb") as fileobj: bytes = fileobj.read(MAGIC_LEN) if bytes == FAT_MAGIC_BYTES: # Read in the fat header fileobj.seek(0) - header = mach_o.fat_header.from_fileobj(fileobj, _endian_='>') + header = mach_o.fat_header.from_fileobj(fileobj, _endian_=">") if header.nfat_arch < 1: return False # Read in the first fat arch header - arch = mach_o.fat_arch.from_fileobj(fileobj, _endian_='>') + arch = mach_o.fat_arch.from_fileobj(fileobj, _endian_=">") fileobj.seek(arch.offset) # Read magic off the first header bytes = fileobj.read(MAGIC_LEN) @@ -227,7 +231,7 @@ def iter_platform_files(dst): """ Walk a directory and yield each full path that is a Mach-O file """ - for root, dirs, files in os.walk(dst): + for root, _dirs, files in os.walk(dst): for fn in files: fn = os.path.join(root, fn) if is_platform_file(fn): @@ -242,7 +246,7 @@ def strip_files(files, argv_max=(256 * 1024)): while tostrip: cmd = list(STRIPCMD) flips = [] - pathlen = sum([len(s) + 1 for s in cmd]) + pathlen = sum(len(s) + 1 for s in cmd) while pathlen < argv_max: if not tostrip: break -- cgit v1.2.3-60-g2f50