[ltrace] Fix building on ARM

Petr Machata pmachata at fedoraproject.org
Tue Nov 5 04:10:10 UTC 2013


commit 51c97fb59ecdb0d6e9632a0a8cc36e2e737be0c8
Author: Petr Machata <pmachata at redhat.com>
Date:   Tue Nov 5 04:58:05 2013 +0100

    Fix building on ARM

 ltrace-0.7.91-arm.patch |  610 +++++++++++++++++++++++++++++++++++++++++++++++
 ltrace.spec             |    4 +
 2 files changed, 614 insertions(+), 0 deletions(-)
---
diff --git a/ltrace-0.7.91-arm.patch b/ltrace-0.7.91-arm.patch
new file mode 100644
index 0000000..84c7d0d
--- /dev/null
+++ b/ltrace-0.7.91-arm.patch
@@ -0,0 +1,610 @@
+diff --git a/ltrace-elf.c b/ltrace-elf.c
+index 92b642b..6f86d56 100644
+--- a/ltrace-elf.c
++++ b/ltrace-elf.c
+@@ -531,6 +531,38 @@ elf_read_relocs(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr,
+ 	return 0;
+ }
+ 
++int
++elf_load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
++{
++	Elf_Scn *scn;
++	GElf_Shdr shdr;
++	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
++	    || scn == NULL) {
++	fail:
++		fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
++			elf_errmsg(-1));
++		return -1;
++	}
++
++	Elf_Data *data = elf_loaddata(scn, &shdr);
++	if (data == NULL)
++		goto fail;
++
++	size_t j;
++	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
++		GElf_Dyn dyn;
++		if (gelf_getdyn(data, j, &dyn) == NULL)
++			goto fail;
++
++		if(dyn.d_tag == tag) {
++			*valuep = dyn.d_un.d_ptr;
++			return 0;
++		}
++	}
++
++	return -1;
++}
++
+ static int
+ ltelf_read_elf(struct ltelf *lte, const char *filename)
+ {
+diff --git a/ltrace-elf.h b/ltrace-elf.h
+index ea14512..db4ffe9 100644
+--- a/ltrace-elf.h
++++ b/ltrace-elf.h
+@@ -139,6 +139,10 @@ struct elf_each_symbol_t {
+ int elf_read_relocs(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr,
+ 		    struct vect *rela_vec);
+ 
++/* Read a given DT_ TAG from LTE.  Value is returned in *VALUEP.
++ * Returns 0 on success or a negative value on failure.  */
++int elf_load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep);
++
+ /* Read, respectively, 1, 2, 4, or 8 bytes from Elf data at given
+  * OFFSET, and store it in *RETP.  Returns 0 on success or a negative
+  * value if there's not enough data.  */
+diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h
+index 58a7fdf..6d0d902 100644
+--- a/sysdeps/linux-gnu/arm/arch.h
++++ b/sysdeps/linux-gnu/arm/arch.h
+@@ -22,6 +22,8 @@
+ #ifndef LTRACE_ARM_ARCH_H
+ #define LTRACE_ARM_ARCH_H
+ 
++#include <libelf.h>
++
+ #define ARCH_HAVE_ENABLE_BREAKPOINT 1
+ #define ARCH_HAVE_DISABLE_BREAKPOINT 1
+ 
+@@ -47,7 +49,7 @@ struct arch_breakpoint_data {
+ 
+ #define ARCH_HAVE_LTELF_DATA
+ struct arch_ltelf_data {
+-	/* We have this only for the hooks.  */
++	Elf_Data *jmprel_data;
+ };
+ 
+ #define ARCH_HAVE_LIBRARY_DATA
+diff --git a/sysdeps/linux-gnu/arm/fetch.c b/sysdeps/linux-gnu/arm/fetch.c
+index 5081d78..b500448 100644
+--- a/sysdeps/linux-gnu/arm/fetch.c
++++ b/sysdeps/linux-gnu/arm/fetch.c
+@@ -32,200 +32,12 @@
+ #include "backend.h"
+ #include "fetch.h"
+ #include "library.h"
+-#include "ltrace-elf.h"
+ #include "proc.h"
+ #include "ptrace.h"
+ #include "regs.h"
+ #include "type.h"
+ #include "value.h"
+ 
+-static int
+-get_hardfp(uint64_t abi_vfp_args)
+-{
+-	if (abi_vfp_args == 2)
+-		fprintf(stderr,
+-			"Tag_ABI_VFP_args value 2 (tool chain-specific "
+-			"conventions) not supported.\n");
+-	return abi_vfp_args == 1;
+-}
+-
+-int
+-arch_elf_init(struct ltelf *lte, struct library *lib)
+-{
+-	/* Nothing in this section is strictly critical.  It's not
+-	 * that much of a deal if we fail to guess right whether the
+-	 * ABI is softfp or hardfp.  */
+-	unsigned hardfp = 0;
+-
+-	Elf_Scn *scn;
+-	Elf_Data *data;
+-	GElf_Shdr shdr;
+-	if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
+-	    || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
+-		fprintf(stderr,
+-			"Error when obtaining ARM attribute section: %s\n",
+-			elf_errmsg(-1));
+-		goto done;
+-
+-	} else if (scn != NULL && data != NULL) {
+-		GElf_Xword offset = 0;
+-		uint8_t version;
+-		if (elf_read_next_u8(data, &offset, &version) < 0) {
+-			goto done;
+-		} else if (version != 'A') {
+-			fprintf(stderr, "Unsupported ARM attribute section "
+-				"version %d ('%c').\n", version, version);
+-			goto done;
+-		}
+-
+-		do {
+-			const char signature[] = "aeabi";
+-			/* N.B. LEN is including the length field
+-			 * itself.  */
+-			uint32_t sec_len;
+-			if (elf_read_u32(data, offset, &sec_len) < 0
+-			    || !elf_can_read_next(data, offset, sec_len)) {
+-				goto done;
+-			}
+-			const GElf_Xword next_offset = offset + sec_len;
+-			offset += 4;
+-
+-			if (sec_len < 4 + sizeof signature
+-			    || strcmp(signature, data->d_buf + offset) != 0)
+-				goto skip;
+-			offset += sizeof signature;
+-
+-			const GElf_Xword offset0 = offset;
+-			uint64_t tag;
+-			uint32_t sub_len;
+-			if (elf_read_next_uleb128(data, &offset, &tag) < 0
+-			    || elf_read_next_u32(data, &offset, &sub_len) < 0
+-			    || !elf_can_read_next(data, offset0, sub_len))
+-				goto done;
+-
+-			if (tag != 1)
+-				/* IHI0045D_ABI_addenda: "section and
+-				 * symbol attributes are deprecated
+-				 * [...] consumers are permitted to
+-				 * ignore them."  */
+-				goto skip;
+-
+-			while (offset < offset0 + sub_len) {
+-				if (elf_read_next_uleb128(data,
+-							  &offset, &tag) < 0)
+-					goto done;
+-
+-				switch (tag) {
+-					uint64_t v;
+-				case 6: /* Tag_CPU_arch */
+-				case 7: /* Tag_CPU_arch_profile */
+-				case 8: /* Tag_ARM_ISA_use */
+-				case 9: /* Tag_THUMB_ISA_use */
+-				case 10: /* Tag_FP_arch */
+-				case 11: /* Tag_WMMX_arch */
+-				case 12: /* Tag_Advanced_SIMD_arch */
+-				case 13: /* Tag_PCS_config */
+-				case 14: /* Tag_ABI_PCS_R9_use */
+-				case 15: /* Tag_ABI_PCS_RW_data */
+-				case 16: /* Tag_ABI_PCS_RO_data */
+-				case 17: /* Tag_ABI_PCS_GOT_use */
+-				case 18: /* Tag_ABI_PCS_wchar_t */
+-				case 19: /* Tag_ABI_FP_rounding */
+-				case 20: /* Tag_ABI_FP_denormal */
+-				case 21: /* Tag_ABI_FP_exceptions */
+-				case 22: /* Tag_ABI_FP_user_exceptions */
+-				case 23: /* Tag_ABI_FP_number_model */
+-				case 24: /* Tag_ABI_align_needed */
+-				case 25: /* Tag_ABI_align_preserved */
+-				case 26: /* Tag_ABI_enum_size */
+-				case 27: /* Tag_ABI_HardFP_use */
+-				case 28: /* Tag_ABI_VFP_args */
+-				case 29: /* Tag_ABI_WMMX_args */
+-				case 30: /* Tag_ABI_optimization_goals */
+-				case 31: /* Tag_ABI_FP_optimization_goals */
+-				case 32: /* Tag_compatibility */
+-				case 34: /* Tag_CPU_unaligned_access */
+-				case 36: /* Tag_FP_HP_extension */
+-				case 38: /* Tag_ABI_FP_16bit_format */
+-				case 42: /* Tag_MPextension_use */
+-				case 70: /* Tag_MPextension_use as well */
+-				case 44: /* Tag_DIV_use */
+-				case 64: /* Tag_nodefaults */
+-				case 66: /* Tag_T2EE_use */
+-				case 68: /* Tag_Virtualization_use */
+-				uleb128:
+-					if (elf_read_next_uleb128
+-						(data, &offset, &v) < 0)
+-						goto done;
+-					if (tag == 28)
+-						hardfp = get_hardfp(v);
+-					if (tag != 32)
+-						continue;
+-
+-					/* Tag 32 has two arguments,
+-					 * fall through.  */
+-
+-				case 4:	/* Tag_CPU_raw_name */
+-				case 5:	/* Tag_CPU_name */
+-				case 65: /* Tag_also_compatible_with */
+-				case 67: /* Tag_conformance */
+-				ntbs:
+-					offset += strlen(data->d_buf
+-							 + offset) + 1;
+-					continue;
+-				}
+-
+-				/* Handle unknown tags in a generic
+-				 * manner, if possible.  */
+-				if (tag <= 32) {
+-					fprintf(stderr,
+-						"Unknown tag %lld "
+-						"at offset %#llx "
+-						"of ARM attribute section.",
+-						tag, offset);
+-					goto skip;
+-				} else if (tag % 2 == 0) {
+-					goto uleb128;
+-				} else {
+-					goto ntbs;
+-				}
+-			}
+-
+-		skip:
+-			offset = next_offset;
+-
+-		} while (elf_can_read_next(data, offset, 1));
+-
+-	}
+-
+-done:
+-	lib->arch.hardfp = hardfp;
+-	return 0;
+-}
+-
+-void
+-arch_elf_destroy(struct ltelf *lte)
+-{
+-}
+-
+-int
+-arch_library_init(struct library *lib)
+-{
+-	return 0;
+-}
+-
+-void
+-arch_library_destroy(struct library *lib)
+-{
+-}
+-
+-int
+-arch_library_clone(struct library *retp, struct library *lib)
+-{
+-	retp->arch = lib->arch;
+-	return 0;
+-}
+-
+ enum {
+ 	/* How many (double) VFP registers the AAPCS uses for
+ 	 * parameter passing.  */
+diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c
+index d1bf7ca..9e9e37f 100644
+--- a/sysdeps/linux-gnu/arm/plt.c
++++ b/sysdeps/linux-gnu/arm/plt.c
+@@ -1,5 +1,6 @@
+ /*
+  * This file is part of ltrace.
++ * Copyright (C) 2013 Petr Machata, Red Hat Inc.
+  * Copyright (C) 2010 Zach Welch, CodeSourcery
+  * Copyright (C) 2004,2008,2009 Juan Cespedes
+  *
+@@ -20,20 +21,205 @@
+  */
+ 
+ #include <gelf.h>
++#include <stdio.h>
++#include <string.h>
+ 
+ #include "proc.h"
+ #include "library.h"
+ #include "ltrace-elf.h"
+ 
+ static int
++get_hardfp(uint64_t abi_vfp_args)
++{
++	if (abi_vfp_args == 2)
++		fprintf(stderr,
++			"Tag_ABI_VFP_args value 2 (tool chain-specific "
++			"conventions) not supported.\n");
++	return abi_vfp_args == 1;
++}
++
++int
++arch_elf_init(struct ltelf *lte, struct library *lib)
++{
++	GElf_Addr jmprel_addr;
++	Elf_Scn *jmprel_sec;
++	GElf_Shdr jmprel_shdr;
++	if (elf_load_dynamic_entry(lte, DT_JMPREL, &jmprel_addr) < 0
++	    || elf_get_section_covering(lte, jmprel_addr,
++					&jmprel_sec, &jmprel_shdr) < 0
++	    || jmprel_sec == NULL)
++		return -1;
++
++	lte->arch.jmprel_data = elf_loaddata(jmprel_sec, &jmprel_shdr);
++	if (lte->arch.jmprel_data == NULL)
++		return -1;
++
++	/* Nothing in this section is strictly critical.  It's not
++	 * that much of a deal if we fail to guess right whether the
++	 * ABI is softfp or hardfp.  */
++	unsigned hardfp = 0;
++
++	Elf_Scn *scn;
++	Elf_Data *data;
++	GElf_Shdr shdr;
++	if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
++	    || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
++		fprintf(stderr,
++			"Error when obtaining ARM attribute section: %s\n",
++			elf_errmsg(-1));
++		goto done;
++
++	} else if (scn != NULL && data != NULL) {
++		GElf_Xword offset = 0;
++		uint8_t version;
++		if (elf_read_next_u8(data, &offset, &version) < 0) {
++			goto done;
++		} else if (version != 'A') {
++			fprintf(stderr, "Unsupported ARM attribute section "
++				"version %d ('%c').\n", version, version);
++			goto done;
++		}
++
++		do {
++			const char signature[] = "aeabi";
++			/* N.B. LEN is including the length field
++			 * itself.  */
++			uint32_t sec_len;
++			if (elf_read_u32(data, offset, &sec_len) < 0
++			    || !elf_can_read_next(data, offset, sec_len)) {
++				goto done;
++			}
++			const GElf_Xword next_offset = offset + sec_len;
++			offset += 4;
++
++			if (sec_len < 4 + sizeof signature
++			    || strcmp(signature, data->d_buf + offset) != 0)
++				goto skip;
++			offset += sizeof signature;
++
++			const GElf_Xword offset0 = offset;
++			uint64_t tag;
++			uint32_t sub_len;
++			if (elf_read_next_uleb128(data, &offset, &tag) < 0
++			    || elf_read_next_u32(data, &offset, &sub_len) < 0
++			    || !elf_can_read_next(data, offset0, sub_len))
++				goto done;
++
++			if (tag != 1)
++				/* IHI0045D_ABI_addenda: "section and
++				 * symbol attributes are deprecated
++				 * [...] consumers are permitted to
++				 * ignore them."  */
++				goto skip;
++
++			while (offset < offset0 + sub_len) {
++				if (elf_read_next_uleb128(data,
++							  &offset, &tag) < 0)
++					goto done;
++
++				switch (tag) {
++					uint64_t v;
++				case 6: /* Tag_CPU_arch */
++				case 7: /* Tag_CPU_arch_profile */
++				case 8: /* Tag_ARM_ISA_use */
++				case 9: /* Tag_THUMB_ISA_use */
++				case 10: /* Tag_FP_arch */
++				case 11: /* Tag_WMMX_arch */
++				case 12: /* Tag_Advanced_SIMD_arch */
++				case 13: /* Tag_PCS_config */
++				case 14: /* Tag_ABI_PCS_R9_use */
++				case 15: /* Tag_ABI_PCS_RW_data */
++				case 16: /* Tag_ABI_PCS_RO_data */
++				case 17: /* Tag_ABI_PCS_GOT_use */
++				case 18: /* Tag_ABI_PCS_wchar_t */
++				case 19: /* Tag_ABI_FP_rounding */
++				case 20: /* Tag_ABI_FP_denormal */
++				case 21: /* Tag_ABI_FP_exceptions */
++				case 22: /* Tag_ABI_FP_user_exceptions */
++				case 23: /* Tag_ABI_FP_number_model */
++				case 24: /* Tag_ABI_align_needed */
++				case 25: /* Tag_ABI_align_preserved */
++				case 26: /* Tag_ABI_enum_size */
++				case 27: /* Tag_ABI_HardFP_use */
++				case 28: /* Tag_ABI_VFP_args */
++				case 29: /* Tag_ABI_WMMX_args */
++				case 30: /* Tag_ABI_optimization_goals */
++				case 31: /* Tag_ABI_FP_optimization_goals */
++				case 32: /* Tag_compatibility */
++				case 34: /* Tag_CPU_unaligned_access */
++				case 36: /* Tag_FP_HP_extension */
++				case 38: /* Tag_ABI_FP_16bit_format */
++				case 42: /* Tag_MPextension_use */
++				case 70: /* Tag_MPextension_use as well */
++				case 44: /* Tag_DIV_use */
++				case 64: /* Tag_nodefaults */
++				case 66: /* Tag_T2EE_use */
++				case 68: /* Tag_Virtualization_use */
++				uleb128:
++					if (elf_read_next_uleb128
++						(data, &offset, &v) < 0)
++						goto done;
++					if (tag == 28)
++						hardfp = get_hardfp(v);
++					if (tag != 32)
++						continue;
++
++					/* Tag 32 has two arguments,
++					 * fall through.  */
++
++				case 4:	/* Tag_CPU_raw_name */
++				case 5:	/* Tag_CPU_name */
++				case 65: /* Tag_also_compatible_with */
++				case 67: /* Tag_conformance */
++				ntbs:
++					offset += strlen(data->d_buf
++							 + offset) + 1;
++					continue;
++				}
++
++				/* Handle unknown tags in a generic
++				 * manner, if possible.  */
++				if (tag <= 32) {
++					fprintf(stderr,
++						"Unknown tag %lld "
++						"at offset %#llx "
++						"of ARM attribute section.",
++						tag, offset);
++					goto skip;
++				} else if (tag % 2 == 0) {
++					goto uleb128;
++				} else {
++					goto ntbs;
++				}
++			}
++
++		skip:
++			offset = next_offset;
++
++		} while (elf_can_read_next(data, offset, 1));
++
++	}
++
++done:
++	lib->arch.hardfp = hardfp;
++	return 0;
++}
++
++void
++arch_elf_destroy(struct ltelf *lte)
++{
++}
++
++static int
+ arch_plt_entry_has_stub(struct ltelf *lte, size_t off) {
+-	uint16_t op = *(uint16_t *)((char *)lte->relplt->d_buf + off);
++	char *buf = (char *) lte->arch.jmprel_data->d_buf;
++	uint16_t op = *(uint16_t *) (buf + off);
+ 	return op == 0x4778;
+ }
+ 
+ GElf_Addr
+ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
+-	size_t start = lte->relplt->d_size + 12;
++	size_t start = lte->arch.jmprel_data->d_size + 12;
+ 	size_t off = start + 20, i;
+ 	for (i = 0; i < ndx; i++)
+ 		off += arch_plt_entry_has_stub(lte, off) ? 16 : 12;
+@@ -47,3 +233,21 @@ sym2addr(struct process *proc, struct library_symbol *sym)
+ {
+ 	return sym->enter_addr;
+ }
++
++int
++arch_library_init(struct library *lib)
++{
++	return 0;
++}
++
++void
++arch_library_destroy(struct library *lib)
++{
++}
++
++int
++arch_library_clone(struct library *retp, struct library *lib)
++{
++	retp->arch = lib->arch;
++	return 0;
++}
+diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
+index 5e3ffe1..3ec1397 100644
+--- a/sysdeps/linux-gnu/ppc/plt.c
++++ b/sysdeps/linux-gnu/ppc/plt.c
+@@ -402,38 +402,6 @@ get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, Elf_Data *plt_data)
+ }
+ 
+ static int
+-load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
+-{
+-	Elf_Scn *scn;
+-	GElf_Shdr shdr;
+-	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
+-	    || scn == NULL) {
+-	fail:
+-		fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
+-			elf_errmsg(-1));
+-		return -1;
+-	}
+-
+-	Elf_Data *data = elf_loaddata(scn, &shdr);
+-	if (data == NULL)
+-		goto fail;
+-
+-	size_t j;
+-	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
+-		GElf_Dyn dyn;
+-		if (gelf_getdyn(data, j, &dyn) == NULL)
+-			goto fail;
+-
+-		if(dyn.d_tag == tag) {
+-			*valuep = dyn.d_un.d_ptr;
+-			return 0;
+-		}
+-	}
+-
+-	return -1;
+-}
+-
+-static int
+ nonzero_data(Elf_Data *data)
+ {
+ 	/* We are not supposed to get here if there's no PLT.  */
+@@ -488,8 +456,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
+ 	Elf_Scn *rela_sec;
+ 	GElf_Shdr rela_shdr;
+ 	if ((lte->ehdr.e_machine == EM_PPC64 || lte->arch.secure_plt)
+-	    && load_dynamic_entry(lte, DT_RELA, &rela) == 0
+-	    && load_dynamic_entry(lte, DT_RELASZ, &relasz) == 0
++	    && elf_load_dynamic_entry(lte, DT_RELA, &rela) == 0
++	    && elf_load_dynamic_entry(lte, DT_RELASZ, &relasz) == 0
+ 	    && elf_get_section_covering(lte, rela, &rela_sec, &rela_shdr) == 0
+ 	    && rela_sec != NULL) {
+ 
+@@ -509,7 +477,7 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
+ 
+ 	if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
+ 		GElf_Addr ppcgot;
+-		if (load_dynamic_entry(lte, DT_PPC_GOT, &ppcgot) < 0) {
++		if (elf_load_dynamic_entry(lte, DT_PPC_GOT, &ppcgot) < 0) {
+ 			fprintf(stderr, "couldn't find DT_PPC_GOT\n");
+ 			return -1;
+ 		}
+@@ -522,7 +490,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
+ 
+ 	} else if (lte->ehdr.e_machine == EM_PPC64) {
+ 		GElf_Addr glink_vma;
+-		if (load_dynamic_entry(lte, DT_PPC64_GLINK, &glink_vma) < 0) {
++		if (elf_load_dynamic_entry(lte, DT_PPC64_GLINK,
++					   &glink_vma) < 0) {
+ 			fprintf(stderr, "couldn't find DT_PPC64_GLINK\n");
+ 			return -1;
+ 		}
+@@ -532,8 +501,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
+ 
+ 	} else {
+ 		/* By exhaustion--PPC32 BSS.  */
+-		if (load_dynamic_entry(lte, DT_PLTGOT,
+-				       &lib->arch.pltgot_addr) < 0) {
++		if (elf_load_dynamic_entry(lte, DT_PLTGOT,
++					   &lib->arch.pltgot_addr) < 0) {
+ 			fprintf(stderr, "couldn't find DT_PLTGOT\n");
+ 			return -1;
+ 		}
diff --git a/ltrace.spec b/ltrace.spec
index 0b090ad..f2c68ff 100644
--- a/ltrace.spec
+++ b/ltrace.spec
@@ -14,6 +14,9 @@ BuildRequires: libselinux-devel
 #  https://alioth.debian.org/frs/?group_id=30892
 Source: ltrace-%{version}.tar.bz2
 
+# Merge of several upstream commits that fixes compilation on ARM.
+Patch0: ltrace-0.7.91-arm.patch
+
 %description
 Ltrace is a debugging program which runs a specified command until the
 command exits.  While the command is executing, ltrace intercepts and
@@ -26,6 +29,7 @@ execution of processes.
 
 %prep
 %setup -q -n %{name}-%{version}
+%patch0 -p1
 
 %build
 %configure --docdir=%{?_pkgdocdir}%{!?_pkgdocdir:%{_docdir}/%{name}-%{version}}


More information about the scm-commits mailing list