aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2013-12-16 20:30:38 +0000
committerFabian Groffen <grobian@gentoo.org>2013-12-16 20:30:38 +0000
commit7fd8cd5dc2f12d1fe7b9c9f1981c9f52fafcd9d3 (patch)
tree3119ad5ae82dc899c9711a98479ad1c9ea2b15fb
parentscanelf: flag object files that have a +x stack (even if it is -w) since its ... (diff)
downloadpax-utils-7fd8cd5dc2f12d1fe7b9c9f1981c9f52fafcd9d3.tar.gz
pax-utils-7fd8cd5dc2f12d1fe7b9c9f1981c9f52fafcd9d3.tar.bz2
pax-utils-7fd8cd5dc2f12d1fe7b9c9f1981c9f52fafcd9d3.zip
scanmacho: add support to read LC_RPATH entries from Mach-O files
-rw-r--r--macho.h15
-rw-r--r--man/scanmacho.docbook5
-rw-r--r--scanmacho.c59
3 files changed, 69 insertions, 10 deletions
diff --git a/macho.h b/macho.h
index 82fc47e..a08933b 100644
--- a/macho.h
+++ b/macho.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2012 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/pax-utils/macho.h,v 1.9 2012/11/04 07:26:24 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/pax-utils/macho.h,v 1.10 2013/12/16 20:30:38 grobian Exp $
*/
#ifndef _MACHO_H
@@ -136,9 +136,16 @@ struct load_command
uint32_t cmdsize;
};
+/* features that are required to be supported are flagged, this is to
+ * make the constants below a bit more readable (although we only use it
+ * once for now) */
+#define LC_REQ_DYLD 0x80000000
+
/* cmd */
#define LC_UUID 0x1b /* Specifies the 128-bit UUID for an image
or its corresponding dSYM file. */
+#define LC_RPATH (0x1c | LC_REQ_DYLD) /* Defines a runpath addition,
+ used in @rpath directives in LC_LOAD_DYLIB. */
#define LC_SEGMENT 0x1 /* Defines a segment of this file to be
mapped into the address space of the
process that loads this file. It also
@@ -245,6 +252,12 @@ struct dylinker_command {
union lc_str name;
};
+struct rpath_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ union lc_str path;
+};
+
struct fat_header
{
uint32_t magic;
diff --git a/man/scanmacho.docbook b/man/scanmacho.docbook
index cc72cc8..f7035d9 100644
--- a/man/scanmacho.docbook
+++ b/man/scanmacho.docbook
@@ -127,6 +127,10 @@
<listitem><para>Scan directories recursively</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-r</option>, <option>--rpath</option></term>
+ <listitem><para>Print RPATH encoded in the Mach-O (LC_RPATH)</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>-S</option>, <option>--soname</option></term>
<listitem><para>Print the Mach-O's shared library name (install_name).</para></listitem>
</varlistentry>
@@ -196,6 +200,7 @@
<listitem><para><emphasis remap='B'>p</emphasis> - filename (minus search)</para></listitem>
<listitem><para><emphasis remap='B'>o</emphasis> - mh_type</para></listitem>
<listitem><para><emphasis remap='B'>O</emphasis> - perms</para></listitem>
+ <listitem><para><emphasis remap='B'>r</emphasis> - rpaths</para></listitem>
<listitem><para><emphasis remap='B'>S</emphasis> - install_name</para></listitem>
</itemizedlist>
</para>
diff --git a/scanmacho.c b/scanmacho.c
index b593d41..7069fe0 100644
--- a/scanmacho.c
+++ b/scanmacho.c
@@ -1,16 +1,16 @@
/*
* Copyright 2008-2012 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanmacho.c,v 1.23 2012/11/04 07:26:24 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanmacho.c,v 1.24 2013/12/16 20:30:38 grobian Exp $
*
* based on scanelf by:
* Copyright 2003-2012 Ned Ludd - <solar@gentoo.org>
* Copyright 2004-2012 Mike Frysinger - <vapier@gentoo.org>
* for Darwin specific fun:
- * 2008-2012 Fabian Groffen - <grobian@gentoo.org>
+ * 2008-2013 Fabian Groffen - <grobian@gentoo.org>
*/
-static const char rcsid[] = "$Id: scanmacho.c,v 1.23 2012/11/04 07:26:24 vapier Exp $";
+static const char rcsid[] = "$Id: scanmacho.c,v 1.24 2013/12/16 20:30:38 grobian Exp $";
const char argv0[] = "scanmacho";
#include "paxinc.h"
@@ -35,6 +35,7 @@ static char dir_recurse = 0;
static char dir_crossmount = 1;
static char show_perms = 0;
static char show_size = 0;
+static char show_rpath = 0;
static char show_needed = 0;
static char show_interp = 0;
static char show_bind = 0;
@@ -53,6 +54,38 @@ static char g_match = 0;
static int match_bits = 0;
static unsigned int match_perms = 0;
+static void scanmacho_file_rpath(
+ fatobj *fobj,
+ char *found_rpath,
+ char **ret,
+ size_t *ret_len)
+{
+ loadcmd *lcmd;
+ uint32_t lc_rpath;
+
+ if (!show_rpath) return;
+
+ lcmd = firstloadcmd(fobj);
+ lc_rpath = MGET(fobj->swapped, LC_RPATH);
+
+ do {
+ if (lcmd->lcmd->cmd == lc_rpath) {
+ struct rpath_command *dlcmd = lcmd->data;
+ char *rpath;
+ rpath = lcmd->data + MGET(fobj->swapped, dlcmd->path.offset);
+ if (*found_rpath)
+ xchrcat(ret, ':', ret_len);
+ xstrcat(ret, rpath, ret_len);
+ *found_rpath = 1;
+ }
+ } while (nextloadcmd(lcmd));
+
+ if (be_wewy_wewy_quiet) return;
+
+ if (!*found_rpath && !be_quiet)
+ xstrcat(ret, " - ", ret_len);
+}
+
static const char *macho_file_needed_lib(
fatobj *fobj,
char *found_needed,
@@ -155,11 +188,12 @@ static char *macho_file_soname(fatobj *fobj, char *found_soname)
static int scanmacho_fatobj(fatobj *fobj)
{
unsigned long i;
- char found_needed, found_interp, found_soname, found_lib, found_file;
+ char found_rpath, found_needed, found_interp, found_soname,
+ found_lib, found_file;
static char *out_buffer = NULL;
static size_t out_len;
- found_needed = found_interp = found_soname = \
+ found_rpath = found_needed = found_interp = found_soname = \
found_lib = found_file = 0;
if (be_verbose > 2)
@@ -190,6 +224,7 @@ static int scanmacho_fatobj(fatobj *fobj)
case 'f': prints("FILE "); found_file = 1; break;
case 'o': prints(" TYPE "); break;
case 'M': prints("CPU "); break;
+ case 'r': prints("RPATH "); break;
case 'n': prints("NEEDED "); break;
case 'i': prints("DYLINKER "); break;
case 'b': prints("FLAGS "); break;
@@ -250,6 +285,7 @@ static int scanmacho_fatobj(fatobj *fobj)
if (be_wewy_wewy_quiet) break;
xstrcat(&out_buffer, fobj->base_filename, &out_len);
break;
+ case 'r': scanmacho_file_rpath(fobj, &found_rpath, &out_buffer, &out_len); break;
case 'o': out = get_machomhtype(fobj); break;
case 'M': out = get_machocputype(fobj); break;
case 'D': out = get_machoendian(fobj); break;
@@ -273,7 +309,7 @@ static int scanmacho_fatobj(fatobj *fobj)
}
#define FOUND_SOMETHING() \
- ( found_needed || found_interp || found_soname || found_lib )
+ (found_rpath || found_needed || found_interp || found_soname || found_lib)
if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
xchrcat(&out_buffer, ' ', &out_len);
@@ -497,8 +533,8 @@ static void scanmacho_envpath(void)
free(path);
}
-/* usage / invocation handling functions */ /* Free Flags: c d e j k l r s t u w x z G H I J K L P Q T U W X Y */
-#define PARSE_FLAGS "pRmyAnibSN:gE:M:DO:ZaqvF:f:o:CBhV"
+/* usage / invocation handling functions */ /* Free Flags: c d e j k l s t u w x z G H I J K L P Q T U W X Y */
+#define PARSE_FLAGS "pRmyArnibSN:gE:M:DO:ZaqvF:f:o:CBhV"
#define a_argument required_argument
static struct option const long_opts[] = {
{"path", no_argument, NULL, 'p'},
@@ -506,6 +542,7 @@ static struct option const long_opts[] = {
{"mount", no_argument, NULL, 'm'},
{"symlink", no_argument, NULL, 'y'},
{"archives", no_argument, NULL, 'A'},
+ {"rpath", no_argument, NULL, 'r'},
{"needed", no_argument, NULL, 'n'},
{"interp", no_argument, NULL, 'i'},
{"bind", no_argument, NULL, 'b'},
@@ -536,6 +573,7 @@ static const char * const opts_help[] = {
"Don't recursively cross mount points",
"Don't scan symlinks",
"Scan archives (.a files)\n",
+ "Print LC_RPATH information (ELF: RPATH/RUNPATH)",
"Print LC_LOAD_DYLIB information (ELF: NEEDED)",
"Print LC_LOAD_DYLINKER information (ELF: INTERP)",
"Print flags from mach_header (ELF: BIND)",
@@ -636,6 +674,7 @@ static int parseargs(int argc, char *argv[])
case 'p': scan_envpath = 1; break;
case 'R': dir_recurse = 1; break;
case 'm': dir_crossmount = 0; break;
+ case 'r': show_rpath = 1; break;
case 'n': show_needed = 1; break;
case 'i': show_interp = 1; break;
case 'b': show_bind = 1; break;
@@ -654,7 +693,7 @@ static int parseargs(int argc, char *argv[])
}
/* let the format option override all other options */
if (out_format) {
- show_needed = show_interp = show_bind = show_soname = \
+ show_rpath = show_needed = show_interp = show_bind = show_soname = \
show_perms = show_endian = show_size = 0;
for (i = 0; out_format[i]; ++i) {
if (!IS_MODIFIER(out_format[i])) continue;
@@ -674,6 +713,7 @@ static int parseargs(int argc, char *argv[])
case 'Z': show_size = 1; break;
case 'D': show_endian = 1; break;
case 'O': show_perms = 1; break;
+ case 'r': show_rpath = 1; break;
case 'n': show_needed = 1; break;
case 'i': show_interp = 1; break;
case 'b': show_bind = 1; break;
@@ -694,6 +734,7 @@ static int parseargs(int argc, char *argv[])
if (show_perms) xstrcat(&out_format, "%O ", &fmt_len);
if (show_size) xstrcat(&out_format, "%Z ", &fmt_len);
if (show_endian) xstrcat(&out_format, "%D ", &fmt_len);
+ if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);