Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [pull request] Pull request for branch perf-elfutils
@ 2013-01-06 15:22 Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 01/15] package: support multiple patches Thomas Petazzoni
                   ` (15 more replies)
  0 siblings, 16 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

Hello,

Here is a set of patches that add the elfutils and perf packages in
Buildroot, based on previous efforts from Stefan Fr?berg and Kaiwan
Billimoria (thanks !).

These packages are not trivial because:
 1) perf is part of the kernel sources
 2) elfutils is a nightmare to build against uClibc

I've been working on this for about two days, trying different
solutions, the one proposed here appeared to be the most reasonable
one in terms of patch size, and maintenability.

Here is a short description of the patches, and the logic behind the
order of the patches:

 * Patches 1 and 2 make it possible to list several patches in the
   <pkg>_PATCH variable of a package .mk file. This is used by the
   elfutils package to apply two big patches that are provided along
   with elfutils tarball. Compared to the previous proposal from
   Stefan Fr?berg, it avoids the need from merging in Buildroot two
   fairly large patches (57K and 62K).

 * Patch 3 adds elfutils as a glibc-only package, to keep things
   simple.

 * Patch 4 allows to disable the installation of elfutils. Instead of
   doing it by removing executable after their installation, I've
   added a configuration option inside elfutils. This will be useful
   to support uClibc, as the elfutils tools are causing issues to
   build with uClibc, and we don't need them to just build the
   elfutils libraries.

 * Patch 5 adds a perf package, with no support for libelf.

 * Patch 6 improves the perf package to use libelf when available
   (thanks to the elfutils package).

 * Patch 7 adds error checking to the perf package to catch kernel
   version problems.

 * Patch 8 builds argp-standalone as position-independent code. This
   is needed as it will be used by the elfutils package in some shared
   library.

 * Patch 9 to 14 are here to progressively make elfutils buildable on
   uClibc. Notice that at this point, it is *NOT* possible to select
   elfutils with a uClibc toolchain. Only the final commit makes that
   possible. So this split of patches is here only to make things
   easier to review (but this split also doesn't break the build, as
   uClibc build of elfutils is not possible until we reach patch 15).

   Most of the patches are relatively simple. The most annoying one is
   the one regarding the fts_*() family of functions. I had basically
   three choices here:

     (1) Enable fts_*() functions in our default uClibc
         configuration. But elfutils is apparently the only package to
         make use of these functions, since even the uClibc help text
         for those functions mention elfutils as the primary reason
         for having support for those functions in uClibc. The help
         text also encourages migrating to the nftw() function
         instead. So, changing our default uClibc configuration didn't
         seem like the right choice.

     (2) Use gnulib to provide fts. This is what Stefan Fr?berg
         initially did. It required a very large (1.5 MB) patch. I
         improved that by creating a host-gnulib package, and then
         call gnulib-tool at build time in the elfutils package so
         that the needed functions are added. But it still required
         changes to the configure.ac file, Makefile.am and so on. So,
         a lot better than the 1.5 MB patch, but still not really
         nice, especially just to get the 'fts' feature.

     (3) Copy the fts_*() functions from uClibc. This is what I've
         decided to implement in this proposal.

 * Patch 15 finally makes elfutils available on uClibc (but only the
   libraries, not the utilities themselves).

The result has been tested on a x86 glibc toolchain, x86 uClibc
toolchain and ARM uClibc toolchain.

Best regards,

Thomas

The following changes since commit 66bfe1d4fe2de50aef6ac3fc836a710fa577cdef:

  xdriver_xf86-video-sunffb: remove package (2013-01-05 14:34:48 +0100)

are available in the git repository at:

  git://git.free-electrons.com/users/thomas-petazzoni/buildroot.git perf-elfutils

for you to fetch changes up to 3e9f9e1a1d4de1c948dcf64dffd1a9e6e653d7bd:

  elfutils: make available on uClibc toolchains (2013-01-06 16:08:29 +0100)

----------------------------------------------------------------
Stefan Fr?berg (1):
      elfutils: new package

Thomas Petazzoni (14):
      package: support multiple patches
      docs/manual: update to mention the multiple patches support
      elfutils: make it possible to only install the libraries
      perf: new package
      perf: allow build against libelf when available
      perf: add kernel version checks
      argp-standlone: build position independent code
      elfutils: towards uClibc support: argp-standalone usage
      elfutils: towards uClibc support: solve memcpy problem
      elfutils: towards uClibc support: requires largefile
      elfutils: towards uClibc support: gettext
      elfutils: towards uClibc support: FTS functions
      elfutils: towards uClibc support: disable po build
      elfutils: make available on uClibc toolchains

 docs/manual/adding-packages-generic.txt          |   17 +-
 package/Config.in                                |    2 +
 package/argp-standalone/argp-standalone.mk       |    3 +
 package/elfutils/Config.in                       |   29 +
 package/elfutils/elfutils-01-disable-progs.patch |   47 +
 package/elfutils/elfutils-02-argp-support.patch  |   92 ++
 package/elfutils/elfutils-03-memcpy-def.patch    |   24 +
 package/elfutils/elfutils-04-fts.patch           | 1307 ++++++++++++++++++++++
 package/elfutils/elfutils-05-disable-po.patch    |   22 +
 package/elfutils/elfutils.mk                     |   70 ++
 package/perf/Config.in                           |   22 +
 package/perf/perf.mk                             |   55 +
 package/pkg-generic.mk                           |   17 +-
 13 files changed, 1695 insertions(+), 12 deletions(-)
 create mode 100644 package/elfutils/Config.in
 create mode 100644 package/elfutils/elfutils-01-disable-progs.patch
 create mode 100644 package/elfutils/elfutils-02-argp-support.patch
 create mode 100644 package/elfutils/elfutils-03-memcpy-def.patch
 create mode 100644 package/elfutils/elfutils-04-fts.patch
 create mode 100644 package/elfutils/elfutils-05-disable-po.patch
 create mode 100644 package/elfutils/elfutils.mk
 create mode 100644 package/perf/Config.in
 create mode 100644 package/perf/perf.mk

Thanks,
-- 
Thomas Petazzoni

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 01/15] package: support multiple patches
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 02/15] docs/manual: update to mention the multiple patches support Thomas Petazzoni
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

With this commit, we extend the behaviour of the <pkg>_PATCH variable
so that it now allows to list several patches to be downloaded and
applied, and no longer just one patch.

This will be useful for the elfutils package, and should anyway not
break the existing behaviour for packages using just one patch.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/pkg-generic.mk |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/package/pkg-generic.mk b/package/pkg-generic.mk
index a570ad7..59de0f0 100644
--- a/package/pkg-generic.mk
+++ b/package/pkg-generic.mk
@@ -28,12 +28,19 @@
 $(BUILD_DIR)/%/.stamp_downloaded:
 ifeq ($(DL_MODE),DOWNLOAD)
 # Only show the download message if it isn't already downloaded
-	$(Q)(test -e $(DL_DIR)/$($(PKG)_SOURCE) && \
-		(test -z $($(PKG)_PATCH) || test -e $(DL_DIR)$($(PKG)_PATCH))) || \
-		$(call MESSAGE,"Downloading")
+	$(Q)if test ! -e $(DL_DIR)/$($(PKG)_SOURCE); then \
+		$(call MESSAGE,"Downloading") ; \
+	else \
+		for p in $($(PKG)_PATCH) ; do \
+			if test ! -e $(DL_DIR)/$$p ; then \
+				$(call MESSAGE,"Downloading") ; \
+				break ; \
+			fi ; \
+		done ; \
+	fi
 endif
 	$(if $($(PKG)_SOURCE),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_SOURCE)))
-	$(if $($(PKG)_PATCH),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_PATCH)))
+	$(foreach p,$($(PKG)_PATCH),$(call DOWNLOAD,$($(PKG)_SITE)/$(p))$(sep))
 	$(foreach hook,$($(PKG)_POST_DOWNLOAD_HOOKS),$(call $(hook))$(sep))
 ifeq ($(DL_MODE),DOWNLOAD)
 	$(Q)mkdir -p $(@D)
@@ -78,7 +85,7 @@ $(BUILD_DIR)/%/.stamp_patched: NAMEVER = $(RAWNAME)-$($(PKG)_VERSION)
 $(BUILD_DIR)/%/.stamp_patched:
 	@$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$(RAWNAME)")
 	$(foreach hook,$($(PKG)_PRE_PATCH_HOOKS),$(call $(hook))$(sep))
-	$(if $($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $($(PKG)_PATCH))
+	$(foreach p,$($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $(p)$(sep))
 	$(Q)( \
 	if test -d $($(PKG)_DIR_PREFIX)/$(RAWNAME); then \
 	  if test "$(wildcard $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER)*.patch*)"; then \
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 02/15] docs/manual: update to mention the multiple patches support
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 01/15] package: support multiple patches Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 03/15] elfutils: new package Thomas Petazzoni
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

After the modification of the <pkg>_PATCH semantic, let's update the
documentation accordingly.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 docs/manual/adding-packages-generic.txt |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/docs/manual/adding-packages-generic.txt b/docs/manual/adding-packages-generic.txt
index 0759d4f..7b8561a 100644
--- a/docs/manual/adding-packages-generic.txt
+++ b/docs/manual/adding-packages-generic.txt
@@ -156,14 +156,17 @@ information is (assuming the package name is +libfoo+) :
   +packagename-$(LIBFOO_VERSION).tar.gz+. +
   Example: +LIBFOO_SOURCE = foobar-$(LIBFOO_VERSION).tar.bz2+
 
-* +LIBFOO_PATCH+ may contain the name of a patch, that will be
-  downloaded from the same location as the tarball indicated in
-  +LIBFOO_SOURCE+. If +HOST_LIBFOO_PATCH+ is not specified, it
-  defaults to +LIBFOO_PATCH+. Note that patches that are included
-  in Buildroot itself use a different mechanism: all files of the
-  form +<packagename>-*.patch+ present in the package directory inside
+* +LIBFOO_PATCH+ may contain a space-separated list of patch file
+  names, that will be downloaded from the same location as the tarball
+  indicated in +LIBFOO_SOURCE+, and then applied to the package source
+  code. If +HOST_LIBFOO_PATCH+ is not specified, it defaults to
+  +LIBFOO_PATCH+. Note that patches that are included in Buildroot
+  itself use a different mechanism: all files of the form
+  +<packagename>-*.patch+ present in the package directory inside
   Buildroot will be applied to the package after extraction (see
-  xref:patch-policy[patching a package]).
+  xref:patch-policy[patching a package]). Finally, patches listed in
+  the +LIBFOO_PATCH+ variable are applied _before_ the patches stored
+  in the Buildroot package directory.
 
 * +LIBFOO_SITE+ provides the location of the package, which can be a
   URL or a local filesystem path. HTTP, FTP and SCP are supported URL
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 03/15] elfutils: new package
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 01/15] package: support multiple patches Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 02/15] docs/manual: update to mention the multiple patches support Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 04/15] elfutils: make it possible to only install the libraries Thomas Petazzoni
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

From: Stefan Fr?berg <stefan.froberg@petroprogram.com>

This patch adds a a package for elfutils. For now, the package is
glibc specific, as adding uClibc support for this package is quite
tedious, and will therefore be done through followup patches.

Heavily based from work done by Stefan Fr?berg, but with many further
modifications by Thomas Petazzoni.

Signed-off-by: Stefan Fr?berg <stefan.froberg@petroprogram.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/Config.in            |    1 +
 package/elfutils/Config.in   |   15 +++++++++++++
 package/elfutils/elfutils.mk |   49 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 package/elfutils/Config.in
 create mode 100644 package/elfutils/elfutils.mk

diff --git a/package/Config.in b/package/Config.in
index 11ff82d..0cf0a2b 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -512,6 +512,7 @@ menu "Other"
 source "package/apr/Config.in"
 source "package/apr-util/Config.in"
 source "package/classpath/Config.in"
+source "package/elfutils/Config.in"
 source "package/fftw/Config.in"
 source "package/libargtable2/Config.in"
 source "package/argp-standalone/Config.in"
diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
new file mode 100644
index 0000000..836ce4c
--- /dev/null
+++ b/package/elfutils/Config.in
@@ -0,0 +1,15 @@
+comment "elfutils requires a glibc toolchain"
+	depends on !(BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
+		     BR2_TOOLCHAIN_CTNG_glibc     || \
+		     BR2_TOOLCHAIN_CTNG_eglibc)
+
+config BR2_PACKAGE_ELFUTILS
+	bool "elfutils"
+	depends on BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
+		   BR2_TOOLCHAIN_CTNG_glibc     || \
+		   BR2_TOOLCHAIN_CTNG_eglibc
+	help
+	  Libraries/utilities to handle ELF objects (drop in
+	  replacement for libelf).
+
+	  https://fedorahosted.org/elfutils
diff --git a/package/elfutils/elfutils.mk b/package/elfutils/elfutils.mk
new file mode 100644
index 0000000..2750060
--- /dev/null
+++ b/package/elfutils/elfutils.mk
@@ -0,0 +1,49 @@
+#############################################################
+#
+# elfutils
+#
+#############################################################
+ELFUTILS_VERSION = 0.155
+ELFUTILS_SOURCE = elfutils-$(ELFUTILS_VERSION).tar.bz2
+ELFUTILS_SITE = https://fedorahosted.org/releases/e/l/elfutils/$(ELFUTILS_VERSION)
+ELFUTILS_LICENSE = GPLv3 GPLv2 LGPLv3
+ELFUTILS_LICENSE_FILES = COPYING COPYING-GPLV2 COPYING-LGPLV3
+
+# The tarball does not have a generated configure script
+ELFUTILS_AUTORECONF = YES
+ELFUTILS_CONF_OPT += --disable-werror
+ELFUTILS_PATCH = \
+	elfutils-portability.patch \
+	elfutils-robustify.patch
+
+ELFUTILS_INSTALL_STAGING = YES
+
+ifeq ($(BR2_LARGEFILE),y)
+# elfutils gets confused when lfs mode is forced, so don't
+ELFUTILS_CONF_ENV += \
+        CFLAGS="$(filter-out -D_FILE_OFFSET_BITS=64,$(TARGET_CFLAGS))" \
+        CPPFLAGS="$(filter-out -D_FILE_OFFSET_BITS=64,$(TARGET_CPPFLAGS))"
+endif
+
+ifeq ($(BR2_PACKAGE_ZLIB),y)
+ ELFUTILS_DEPENDENCIES += zlib
+ ELFUTILS_CONF_OPT += --with-zlib
+else
+ ELFUTILS_CONF_OPT += --without-zlib
+endif
+
+ifeq ($(BR2_PACKAGE_BZIP2),y)
+ ELFUTILS_DEPENDENCIES += bzip2
+ ELFUTILS_CONF_OPT += --with-bzlib
+else
+ ELFUTILS_CONF_OPT += --without-bzlib
+endif
+
+ifeq ($(BR2_PACKAGE_XZ),y)
+ ELFUTILS_DEPENDENCIES += xz
+ ELFUTILS_CONF_OPT += --with-lzma
+else
+ ELFUTILS_CONF_OPT += --without-lzma
+endif
+
+$(eval $(autotools-package))
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 04/15] elfutils: make it possible to only install the libraries
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (2 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 03/15] elfutils: new package Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 05/15] perf: new package Thomas Petazzoni
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

Add and use a --{enable,disable}-progs configuration option to
selectively enable or disable the elfutils programs. Generally, on an
embedded system, the libraries are more useful than the programs, and
being able to not build the programs will make it easier to build the
elfutils libraries on uClibc.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/Config.in                       |   13 ++++++
 package/elfutils/elfutils-01-disable-progs.patch |   47 ++++++++++++++++++++++
 package/elfutils/elfutils.mk                     |    6 +++
 3 files changed, 66 insertions(+)
 create mode 100644 package/elfutils/elfutils-01-disable-progs.patch

diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
index 836ce4c..87744b5 100644
--- a/package/elfutils/Config.in
+++ b/package/elfutils/Config.in
@@ -12,4 +12,17 @@ config BR2_PACKAGE_ELFUTILS
 	  Libraries/utilities to handle ELF objects (drop in
 	  replacement for libelf).
 
+	  Note that this option only installs the libraries, and not
+	  the programs.
+
 	  https://fedorahosted.org/elfutils
+
+if BR2_PACKAGE_ELFUTILS
+
+config BR2_PACKAGE_ELFUTILS_PROGS
+	bool "Install programs"
+	help
+	  This option tells elfutils to not only install the libelf
+	  libraries, but also the elfutils programs.
+
+endif
diff --git a/package/elfutils/elfutils-01-disable-progs.patch b/package/elfutils/elfutils-01-disable-progs.patch
new file mode 100644
index 0000000..462de89
--- /dev/null
+++ b/package/elfutils/elfutils-01-disable-progs.patch
@@ -0,0 +1,47 @@
+Add a --{enable,disable}-progs configure option
+
+Add a --{enable,disable}-progs configuration option to elfutils. This
+allows to selectively disable the compilation of the elfutils programs
+(in which case only the libraries are built and installed). This is
+useful because the programs are often not needed, and also because
+building the programs against uClibc causes several issues (lack of
+obstack_printf() in uClibc for example).
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/Makefile.am
+===================================================================
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -22,9 +22,13 @@
+ 
+ pkginclude_HEADERS = version.h
+ 
++if ENABLE_PROGS
++PROGS_SUBDIR = src
++endif
++
+ # Add doc back when we have some real content.
+ SUBDIRS = config m4 lib libelf libebl libdwfl libdw libcpu libasm backends \
+-	  src po tests
++	  $(PROGS_SUBDIR) po tests
+ 
+ EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
+ 	     COPYING COPYING-GPLV2 COPYING-LGPLV3
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -263,6 +263,12 @@
+ AC_DEFINE_UNQUOTED(LIBEBL_SUBDIR, "$LIBEBL_SUBDIR")
+ AH_TEMPLATE([LIBEBL_SUBDIR], [$libdir subdirectory containing libebl modules.])
+ 
++AC_ARG_ENABLE([progs],
++	AS_HELP_STRING([--enable-progs], [enable progs]),
++	enable_progs=$enableval,
++	enable_progs=yes)
++AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes)
++
+ dnl Test for zlib and bzlib, gives ZLIB/BZLIB .am
+ dnl conditional and config.h USE_ZLIB/USE_BZLIB #define.
+ save_LIBS="$LIBS"
diff --git a/package/elfutils/elfutils.mk b/package/elfutils/elfutils.mk
index 2750060..f8a4e85 100644
--- a/package/elfutils/elfutils.mk
+++ b/package/elfutils/elfutils.mk
@@ -46,4 +46,10 @@ else
  ELFUTILS_CONF_OPT += --without-lzma
 endif
 
+ifeq ($(BR2_PACKAGE_ELFUTILS_PROGS),y)
+ ELFUTILS_CONF_OPT += --enable-progs
+else
+ ELFUTILS_CONF_OPT += --disable-progs
+endif
+
 $(eval $(autotools-package))
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 05/15] perf: new package
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (3 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 04/15] elfutils: make it possible to only install the libraries Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 06/15] perf: allow build against libelf when available Thomas Petazzoni
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

This patch adds a new package that allows to build the 'perf'
userspace tool that comes in the tools/perf directory of the kernel
sources.

It is an alternative proposal to the one done by Kaiwan Billimoria
<kaiwan.billimoria@gmail.com>, in that it creates the package in
package/perf/. It therefore properly integrates with the Buildroot
package infrastructure.

Of course, the package depends on the Linux kernel to be built by
Buildroot, in order to get Perf sources matching the version of the
kernel that will be executed.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/Config.in      |    1 +
 package/perf/Config.in |   22 ++++++++++++++++++++++
 package/perf/perf.mk   |   39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)
 create mode 100644 package/perf/Config.in
 create mode 100644 package/perf/perf.mk

diff --git a/package/Config.in b/package/Config.in
index 0cf0a2b..0584462 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -35,6 +35,7 @@ source "package/ltrace/Config.in"
 source "package/memstat/Config.in"
 source "package/netperf/Config.in"
 source "package/oprofile/Config.in"
+source "package/perf/Config.in"
 source "package/ramspeed/Config.in"
 source "package/rt-tests/Config.in"
 source "package/strace/Config.in"
diff --git a/package/perf/Config.in b/package/perf/Config.in
new file mode 100644
index 0000000..54b24fe
--- /dev/null
+++ b/package/perf/Config.in
@@ -0,0 +1,22 @@
+config BR2_PACKAGE_PERF
+	bool "perf"
+	depends on BR2_LINUX_KERNEL
+	depends on BR2_LARGEFILE
+	help
+	  perf (sometimes "Perf Events" or perf tools, originally
+	  "Performance Counters for Linux") - is a performance
+	  analyzing tool in Linux, available from kernel version
+	  2.6.31. User-space controlling utility, called 'perf' has
+	  git-like interface with subcommands. It is capable of
+	  statistical profiling of entire system (both kernel and user
+	  code), single CPU or severals threads.
+
+	  This package builds and install the userspace 'perf'
+	  command. It is up to the user to ensure that the kernel
+	  configuration has all suitable options enable to allow a
+	  proper operation of 'perf'.
+
+	  https://perf.wiki.kernel.org/
+
+comment "perf only available if Linux kernel is enabled, and requires largefile support"
+	depends on !BR2_LINUX_KERNEL || !BR2_LARGEFILE
diff --git a/package/perf/perf.mk b/package/perf/perf.mk
new file mode 100644
index 0000000..2aef900
--- /dev/null
+++ b/package/perf/perf.mk
@@ -0,0 +1,39 @@
+#############################################################
+#
+# perf
+#
+#############################################################
+
+# Source taken from the Linux kernel tree
+PERF_SOURCE =
+PERF_VERSION = $(call qstrip,$(BR2_LINUX_KERNEL_VERSION))
+
+PERF_DEPENDENCIES = linux
+
+PERF_MAKE_FLAGS = \
+	$(LINUX_MAKE_FLAGS) \
+	NO_LIBELF=1 \
+	NO_DWARF=1 \
+	NO_LIBAUDIT=1 \
+	NO_NEWT=1 \
+	NO_GTK2=1 \
+	NO_LIBPERL=1 \
+	NO_LIBPYTHON=1 \
+	DESTDIR=$(TARGET_DIR) \
+	prefix=/usr \
+	WERROR=0
+
+define PERF_BUILD_CMDS
+	$(MAKE) -C $(LINUX_DIR)/tools/perf \
+		$(PERF_MAKE_FLAGS) O=$(@D)
+endef
+
+# After installation, we remove the Perl and Python scripts from the
+# target.
+define PERF_INSTALL_TARGET_CMDS
+	$(MAKE) -C $(LINUX_DIR)/tools/perf \
+		$(PERF_MAKE_FLAGS) O=$(@D) install
+	$(RM) -rf $(TARGET_DIR)/usr/libexec/perf-core/scripts/
+endef
+
+$(eval $(generic-package))
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 06/15] perf: allow build against libelf when available
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (4 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 05/15] perf: new package Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 07/15] perf: add kernel version checks Thomas Petazzoni
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

Now that libelf is available thanks to elfutils (for glibc only),
allow to build perf against it if available.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/perf/perf.mk |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/package/perf/perf.mk b/package/perf/perf.mk
index 2aef900..eed30a2 100644
--- a/package/perf/perf.mk
+++ b/package/perf/perf.mk
@@ -12,8 +12,6 @@ PERF_DEPENDENCIES = linux
 
 PERF_MAKE_FLAGS = \
 	$(LINUX_MAKE_FLAGS) \
-	NO_LIBELF=1 \
-	NO_DWARF=1 \
 	NO_LIBAUDIT=1 \
 	NO_NEWT=1 \
 	NO_GTK2=1 \
@@ -23,6 +21,12 @@ PERF_MAKE_FLAGS = \
 	prefix=/usr \
 	WERROR=0
 
+ifeq ($(BR2_PACKAGE_ELFUTILS),y)
+	PERF_DEPENDENCIES += elfutils
+else
+	PERF_MAKE_FLAGS += NO_LIBELF=1 NO_DWARF=1
+endif
+
 define PERF_BUILD_CMDS
 	$(MAKE) -C $(LINUX_DIR)/tools/perf \
 		$(PERF_MAKE_FLAGS) O=$(@D)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 07/15] perf: add kernel version checks
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (5 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 06/15] perf: allow build against libelf when available Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 08/15] argp-standlone: build position independent code Thomas Petazzoni
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

perf is only available since kernel 2.6.31, so if we can't find
tools/perf/Makefile, error out and tell the user about this.

perf without libelf can only be built since kernel 3.7, so error out
and tell the user about this if he's trying to build perf from a < 3.7
kernel without libelf.

Unfortunately, those tests can only be build-time checks as we either
need to know the real kernel version (i.e, using LINUX_VERSION would
not be correct as it can be a Git commit ID, or Git tag), or have
access to the kernel sources themselves. So we can't prevent those
invalid situations at the configuration, we can only nicely tell the
user at build time.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/perf/perf.mk |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/package/perf/perf.mk b/package/perf/perf.mk
index eed30a2..4356f5d 100644
--- a/package/perf/perf.mk
+++ b/package/perf/perf.mk
@@ -28,6 +28,18 @@ else
 endif
 
 define PERF_BUILD_CMDS
+	$(Q)if test ! -f $(LINUX_DIR)/tools/perf/Makefile ; then \
+		echo "Your kernel version is too old and does not have the perf tool." ; \
+		echo "At least kernel 2.6.31 must be used." ; \
+		exit 1 ; \
+	fi
+	$(Q)if test "$(BR2_PACKAGE_ELFUTILS)" = "" ; then \
+		if ! grep -q NO_LIBELF $(LINUX_DIR)/tools/perf/Makefile ; then \
+			echo "The perf tool in your kernel cannot be built without libelf." ; \
+			echo "Either upgrade your kernel to >= 3.7, or enable the elfutils package." ; \
+			exit 1 ; \
+		fi \
+	fi
 	$(MAKE) -C $(LINUX_DIR)/tools/perf \
 		$(PERF_MAKE_FLAGS) O=$(@D)
 endef
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 08/15] argp-standlone: build position independent code
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (6 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 07/15] perf: add kernel version checks Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 09/15] elfutils: towards uClibc support: argp-standalone usage Thomas Petazzoni
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

Even though argp-standalone is built as a static library, it might get
linked in a shared library, so we must built it as
position-independent code.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/argp-standalone/argp-standalone.mk |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/package/argp-standalone/argp-standalone.mk b/package/argp-standalone/argp-standalone.mk
index 47c09b2..ba7f757 100644
--- a/package/argp-standalone/argp-standalone.mk
+++ b/package/argp-standalone/argp-standalone.mk
@@ -8,6 +8,9 @@ ARGP_STANDALONE_VERSION = 1.3
 ARGP_STANDALONE_SITE = http://www.lysator.liu.se/~nisse/archive
 ARGP_STANDALONE_INSTALL_STAGING = YES
 
+ARGP_STANDALONE_CONF_ENV = \
+	CFLAGS="$(TARGET_CFLAGS) -fPIC"
+
 define ARGP_STANDALONE_INSTALL_STAGING_CMDS
 	$(INSTALL) -D $(@D)/libargp.a $(STAGING_DIR)/usr/lib/libargp.a
 	$(INSTALL) -D $(@D)/argp.h $(STAGING_DIR)/usr/include/argp.h
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 09/15] elfutils: towards uClibc support: argp-standalone usage
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (7 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 08/15] argp-standlone: build position independent code Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 10/15] elfutils: towards uClibc support: solve memcpy problem Thomas Petazzoni
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

elfutils uses the argp family of functions, that isn't available in
uClibc. So, we add a dependency on argp-standalone if building with
uClibc, and modify elfutils source code to link against argp if
needed.

Heavily based from work done by Stefan Fr?berg, but with many further
modifications by Thomas Petazzoni.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/Config.in                      |    4 +
 package/elfutils/elfutils-02-argp-support.patch |   92 +++++++++++++++++++++++
 package/elfutils/elfutils.mk                    |    4 +
 3 files changed, 100 insertions(+)
 create mode 100644 package/elfutils/elfutils-02-argp-support.patch

diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
index 87744b5..ee1e4ab 100644
--- a/package/elfutils/Config.in
+++ b/package/elfutils/Config.in
@@ -8,6 +8,10 @@ config BR2_PACKAGE_ELFUTILS
 	depends on BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
 		   BR2_TOOLCHAIN_CTNG_glibc     || \
 		   BR2_TOOLCHAIN_CTNG_eglibc
+	select BR2_PACKAGE_ARGP_STANDALONE if \
+	       BR2_TOOLCHAIN_BUILDROOT   || \
+	       BR2_TOOLCHAIN_CTNG_uClibc || \
+	       BR2_TOOLCHAIN_EXTERNAL_UCLIBC
 	help
 	  Libraries/utilities to handle ELF objects (drop in
 	  replacement for libelf).
diff --git a/package/elfutils/elfutils-02-argp-support.patch b/package/elfutils/elfutils-02-argp-support.patch
new file mode 100644
index 0000000..f81ac8f
--- /dev/null
+++ b/package/elfutils/elfutils-02-argp-support.patch
@@ -0,0 +1,92 @@
+Allow the usage of an external implementation of the argp functions
+
+uClibc lack the argp family of functions that glibc has. Therefore, we
+add a check in the configure script to see if argp_parse is available
+in the C library. If not, we look if it is available in the additional
+'argp' library. If so, we link against that library. If not, we error
+out.
+
+This allows to build elfutils against uClibc with an external argp
+library.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -269,6 +269,13 @@
+ 	enable_progs=yes)
+ AM_CONDITIONAL(ENABLE_PROGS, test "$enable_progs" = yes)
+ 
++AC_CHECK_FUNC([argp_parse])
++if test "$ac_cv_func_argp_parse" != yes; then
++   AC_CHECK_LIB([argp],[argp_parse],ARGP_LIBS=-largp,
++		AC_MSG_ERROR([No argp_parse function available.]))
++fi
++AC_SUBST(ARGP_LIBS)
++
+ dnl Test for zlib and bzlib, gives ZLIB/BZLIB .am
+ dnl conditional and config.h USE_ZLIB/USE_BZLIB #define.
+ save_LIBS="$LIBS"
+Index: b/src/Makefile.am
+===================================================================
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -98,26 +98,29 @@
+ # Buggy old compilers.
+ readelf_no_Werror = yes
+ 
+-readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
++readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \
++	$(ARGP_LIBS)
+ nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \
+-	   $(demanglelib)
+-size_LDADD = $(libelf) $(libeu) $(libmudflap)
+-strip_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
+-ld_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
++	   $(demanglelib) $(ARGP_LIBS)
++size_LDADD = $(libelf) $(libeu) $(libmudflap) $(ARGP_LIBS)
++strip_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl $(ARGP_LIBS)
++ld_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl $(ARGP_LIBS)
+ if NATIVE_LD
+ # -ldl is always needed for libebl.
+ ld_LDADD += libld_elf.a
+ endif
+ ld_LDFLAGS = -rdynamic
+-elflint_LDADD  = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
+-findtextrel_LDADD = $(libdw) $(libelf) $(libmudflap)
+-addr2line_LDADD = $(libdw) $(libelf) $(libmudflap)
+-elfcmp_LDADD = $(libebl) $(libelf) $(libmudflap) -ldl
+-objdump_LDADD  = $(libasm) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
+-ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
+-strings_LDADD = $(libelf) $(libeu) $(libmudflap)
+-ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
+-unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl
++elflint_LDADD  = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl $(ARGP_LIBS)
++findtextrel_LDADD = $(libdw) $(libelf) $(libmudflap) $(ARGP_LIBS)
++addr2line_LDADD = $(libdw) $(libelf) $(libmudflap) $(ARGP_LIBS)
++elfcmp_LDADD = $(libebl) $(libelf) $(libmudflap) -ldl $(ARGP_LIBS)
++objdump_LDADD  = $(libasm) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \
++	$(ARGP_LIBS)
++ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) $(ARGP_LIBS)
++strings_LDADD = $(libelf) $(libeu) $(libmudflap) $(ARGP_LIBS)
++ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) $(ARGP_LIBS)
++unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl \
++	$(ARGP_LIBS)
+ 
+ ldlex.o: ldscript.c
+ ldlex_no_Werror = yes
+Index: b/libdw/Makefile.am
+===================================================================
+--- a/libdw/Makefile.am
++++ b/libdw/Makefile.am
+@@ -111,7 +111,7 @@
+ 		-Wl,--enable-new-dtags,-rpath,$(pkglibdir) \
+ 		-Wl,--version-script,$<,--no-undefined \
+ 		-Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\
+-		-ldl $(zip_LIBS)
++		-ldl $(zip_LIBS) $(ARGP_LIBS)
+ 	if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+ 	ln -fs $@ $@.$(VERSION)
+ 
diff --git a/package/elfutils/elfutils.mk b/package/elfutils/elfutils.mk
index f8a4e85..9f9de52 100644
--- a/package/elfutils/elfutils.mk
+++ b/package/elfutils/elfutils.mk
@@ -25,6 +25,10 @@ ELFUTILS_CONF_ENV += \
         CPPFLAGS="$(filter-out -D_FILE_OFFSET_BITS=64,$(TARGET_CPPFLAGS))"
 endif
 
+ifeq ($(BR2_TOOLCHAIN_BUILDROOT)$(BR2_TOOLCHAIN_EXTERNAL_UCLIBC)$(BR2_TOOLCHAIN_CTNG_uClibc),y)
+ ELFUTILS_DEPENDENCIES += argp-standalone
+endif
+
 ifeq ($(BR2_PACKAGE_ZLIB),y)
  ELFUTILS_DEPENDENCIES += zlib
  ELFUTILS_CONF_OPT += --with-zlib
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 10/15] elfutils: towards uClibc support: solve memcpy problem
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (8 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 09/15] elfutils: towards uClibc support: argp-standalone usage Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 11/15] elfutils: towards uClibc support: requires largefile Thomas Petazzoni
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

elfutils uses some strange internal alias of memcpy in glibc, so
workaround this when building with uClibc.

Heavily based from work done by Stefan Fr?berg, but with many further
modifications by Thomas Petazzoni.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/elfutils-03-memcpy-def.patch |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 package/elfutils/elfutils-03-memcpy-def.patch

diff --git a/package/elfutils/elfutils-03-memcpy-def.patch b/package/elfutils/elfutils-03-memcpy-def.patch
new file mode 100644
index 0000000..eb50cf6
--- /dev/null
+++ b/package/elfutils/elfutils-03-memcpy-def.patch
@@ -0,0 +1,24 @@
+Provide a compatibility alias __memcpy
+
+For some reason, libelf uses the internal glibc alias __memcpy, which
+doesn't exist in uClibc. Add a manual alias so that the build can
+proceed with uClibc.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/libelf/libelf.h
+===================================================================
+--- a/libelf/libelf.h
++++ b/libelf/libelf.h
+@@ -34,6 +34,11 @@
+ /* Get the ELF types.  */
+ #include <elf.h>
+ 
++#ifndef _LIBC
++#ifndef __mempcpy
++#define __mempcpy mempcpy
++#endif
++#endif
+ 
+ /* Known translation types.  */
+ typedef enum
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 11/15] elfutils: towards uClibc support: requires largefile
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (9 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 10/15] elfutils: towards uClibc support: solve memcpy problem Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 12/15] elfutils: towards uClibc support: gettext Thomas Petazzoni
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

elfutils unconditionally uses off64_t for example, so largefile is
needed.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/Config.in |    1 +
 1 file changed, 1 insertion(+)

diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
index ee1e4ab..5ec4ca9 100644
--- a/package/elfutils/Config.in
+++ b/package/elfutils/Config.in
@@ -12,6 +12,7 @@ config BR2_PACKAGE_ELFUTILS
 	       BR2_TOOLCHAIN_BUILDROOT   || \
 	       BR2_TOOLCHAIN_CTNG_uClibc || \
 	       BR2_TOOLCHAIN_EXTERNAL_UCLIBC
+	depends on BR2_LARGEFILE
 	help
 	  Libraries/utilities to handle ELF objects (drop in
 	  replacement for libelf).
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 12/15] elfutils: towards uClibc support: gettext
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (10 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 11/15] elfutils: towards uClibc support: requires largefile Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 13/15] elfutils: towards uClibc support: FTS functions Thomas Petazzoni
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

elfutils is annoying: it needs gettext even if locale support is
disabled...

Heavily based from work done by Stefan Fr?berg, but with many further
modifications by Thomas Petazzoni.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/Config.in   |    1 +
 package/elfutils/elfutils.mk |   11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
index 5ec4ca9..78d02a5 100644
--- a/package/elfutils/Config.in
+++ b/package/elfutils/Config.in
@@ -12,6 +12,7 @@ config BR2_PACKAGE_ELFUTILS
 	       BR2_TOOLCHAIN_BUILDROOT   || \
 	       BR2_TOOLCHAIN_CTNG_uClibc || \
 	       BR2_TOOLCHAIN_EXTERNAL_UCLIBC
+	select BR2_PACKAGE_GETTEXT if BR2_NEEDS_GETTEXT
 	depends on BR2_LARGEFILE
 	help
 	  Libraries/utilities to handle ELF objects (drop in
diff --git a/package/elfutils/elfutils.mk b/package/elfutils/elfutils.mk
index 9f9de52..39407db 100644
--- a/package/elfutils/elfutils.mk
+++ b/package/elfutils/elfutils.mk
@@ -25,6 +25,17 @@ ELFUTILS_CONF_ENV += \
         CPPFLAGS="$(filter-out -D_FILE_OFFSET_BITS=64,$(TARGET_CPPFLAGS))"
 endif
 
+ELFUTILS_LDFLAGS = $(TARGET_LDFLAGS)
+
+# Unconditionnally requires gettext.
+ifeq ($(BR2_NEEDS_GETTEXT),y)
+ELFUTILS_DEPENDENCIES += gettext
+ELFUTILS_LDFLAGS += -lintl
+endif
+
+ELFUTILS_CONF_ENV += \
+	LDFLAGS="$(ELFUTILS_LDFLAGS)"
+
 ifeq ($(BR2_TOOLCHAIN_BUILDROOT)$(BR2_TOOLCHAIN_EXTERNAL_UCLIBC)$(BR2_TOOLCHAIN_CTNG_uClibc),y)
  ELFUTILS_DEPENDENCIES += argp-standalone
 endif
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 13/15] elfutils: towards uClibc support: FTS functions
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (11 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 12/15] elfutils: towards uClibc support: gettext Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 14/15] elfutils: towards uClibc support: disable po build Thomas Petazzoni
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

The fts_*() functions are optional in uClibc, and not compiled in our
default configuration. The best option would be to migrate this
elfutils code to the nftw family of functions, but it requires quite
some work.

So we have several options here:

 *) Enable fts_*() functions in our default uClibc configuration. Not
    nice since only one package needs them (the help text of uClibc
    for fts_*() functions explicitly mention that they have been added
    to be able to build elfutils).

 *) Use gnulib, but it is quite heavy to setup, requires modifications
    to configure.ac, and other things.

 *) Copy the fts function from uClibc into elfutils source code. This
    is the solution used below. uClibc is LGPL, and elfutils is
    LGPL/GPL, so there should not be any licensing issue.

Of course, the fts_*() functions are only built if they are not
already provided by the C library.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/elfutils-04-fts.patch | 1307 ++++++++++++++++++++++++++++++++
 1 file changed, 1307 insertions(+)
 create mode 100644 package/elfutils/elfutils-04-fts.patch

diff --git a/package/elfutils/elfutils-04-fts.patch b/package/elfutils/elfutils-04-fts.patch
new file mode 100644
index 0000000..7318236
--- /dev/null
+++ b/package/elfutils/elfutils-04-fts.patch
@@ -0,0 +1,1307 @@
+Add an implementation of the fts_*() functions
+
+The fts_*() functions are optional in uClibc, and not compiled in our
+default configuration. The best option would be to migrate this
+elfutils code to the nftw family of functions, but it requires quite
+some work.
+
+So we have several options here:
+
+ *) Enable fts_*() functions in our default uClibc configuration. Not
+    nice since only one package needs them (the help text of uClibc
+    for fts_*() functions explicitly mention that they have been added
+    to be able to build elfutils).
+
+ *) Use gnulib, but it is quite heavy to setup, requires modifications
+    to configure.ac, and other things.
+
+ *) Copy the fts function from uClibc into elfutils source code. This
+    is the solution used below. uClibc is LGPL, and elfutils is
+    LGPL/GPL, so there should not be any licensing issue.
+
+Of course, the fts_*() functions are only built if they are not
+already provided by the C library.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -276,6 +276,10 @@
+ fi
+ AC_SUBST(ARGP_LIBS)
+ 
++AC_CHECK_HEADER([fts.h],
++	AC_DEFINE([HAVE_FTS_H], [], [Define if <fts.h> is available in C library]))
++AM_CONDITIONAL(HAVE_FTS, test "$ac_cv_header_fts_h" = yes)
++
+ dnl Test for zlib and bzlib, gives ZLIB/BZLIB .am
+ dnl conditional and config.h USE_ZLIB/USE_BZLIB #define.
+ save_LIBS="$LIBS"
+Index: b/libdwfl/Makefile.am
+===================================================================
+--- a/libdwfl/Makefile.am
++++ b/libdwfl/Makefile.am
+@@ -79,6 +79,9 @@
+ if LZMA
+ libdwfl_a_SOURCES += lzma.c
+ endif
++if !HAVE_FTS
++libdwfl_a_SOURCES += fts.c
++endif
+ 
+ if MUDFLAP
+ libdwfl = libdwfl.a $(libdw) $(libebl) $(libelf) $(libeu)
+Index: b/libdwfl/fts.c
+===================================================================
+--- /dev/null
++++ b/libdwfl/fts.c
+@@ -0,0 +1,1095 @@
++/*-
++ * Copyright (c) 1990, 1993, 1994
++ *	The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#include <sys/param.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <dirent.h>
++#include <errno.h>
++#include "fts_.h"
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++/* Largest alignment size needed, minus one.
++   Usually long double is the worst case.  */
++#ifndef ALIGNBYTES
++#define ALIGNBYTES	(__alignof__ (long double) - 1)
++#endif
++/* Align P to that size.  */
++#ifndef ALIGN
++#define	ALIGN(p)	(((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
++#endif
++
++
++static FTSENT	*fts_alloc (FTS *, const char *, size_t);
++static FTSENT	*fts_build (FTS *, int);
++static void	 fts_lfree (FTSENT *);
++static void	 fts_load (FTS *, FTSENT *);
++static size_t	 fts_maxarglen (char * const *);
++static void	 fts_padjust (FTS *, FTSENT *);
++static int	 fts_palloc (FTS *, size_t);
++static FTSENT	*fts_sort (FTS *, FTSENT *, int);
++static u_short	 fts_stat (FTS *, FTSENT *, int);
++static int      fts_safe_changedir (FTS *, FTSENT *, int, const char *);
++
++#ifndef MAX
++#define MAX(a, b)	({ __typeof__ (a) _a = (a); \
++			   __typeof__ (b) _b = (b); \
++			   _a > _b ? _a : _b; })
++#endif
++
++#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
++
++#define CLR(opt)	(sp->fts_options &= ~(opt))
++#define	ISSET(opt)	(sp->fts_options & (opt))
++#define	SET(opt)	(sp->fts_options |= (opt))
++
++#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
++
++/* fts_build flags */
++#define	BCHILD		1		/* fts_children */
++#define	BNAMES		2		/* fts_children, names only */
++#define	BREAD		3		/* fts_read */
++
++FTS *
++fts_open( char * const *argv, register int options,
++		int (*compar) (const FTSENT **, const FTSENT **))
++{
++	register FTS *sp;
++	register FTSENT *p, *root;
++	register int nitems;
++	FTSENT *parent = NULL;
++	FTSENT *tmp = NULL;
++
++	/* Options check. */
++	if (options & ~FTS_OPTIONMASK) {
++		errno = EINVAL;
++		return (NULL);
++	}
++
++	/* Allocate/initialize the stream */
++	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
++		return (NULL);
++	memset(sp, 0, sizeof(FTS));
++	sp->fts_compar = (int (*) (const void *, const void *)) compar;
++	sp->fts_options = options;
++
++	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
++	if (ISSET(FTS_LOGICAL))
++		SET(FTS_NOCHDIR);
++
++	/*
++	 * Start out with 1K of path space, and enough, in any case,
++	 * to hold the user's paths.
++	 */
++#ifndef MAXPATHLEN
++#define MAXPATHLEN 1024
++#endif
++	size_t maxarglen = fts_maxarglen(argv);
++	if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
++		goto mem1;
++
++	/* Allocate/initialize root's parent. */
++	if (*argv != NULL) {
++		if ((parent = fts_alloc(sp, "", 0)) == NULL)
++			goto mem2;
++		parent->fts_level = FTS_ROOTPARENTLEVEL;
++	  }
++
++	/* Allocate/initialize root(s). */
++	for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
++		/* Don't allow zero-length paths. */
++		size_t len = strlen(*argv);
++		if (len == 0) {
++			errno = ENOENT;
++			goto mem3;
++		}
++
++		p = fts_alloc(sp, *argv, len);
++		p->fts_level = FTS_ROOTLEVEL;
++		p->fts_parent = parent;
++		p->fts_accpath = p->fts_name;
++		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
++
++		/* Command-line "." and ".." are real directories. */
++		if (p->fts_info == FTS_DOT)
++			p->fts_info = FTS_D;
++
++		/*
++		 * If comparison routine supplied, traverse in sorted
++		 * order; otherwise traverse in the order specified.
++		 */
++		if (compar) {
++			p->fts_link = root;
++			root = p;
++		} else {
++			p->fts_link = NULL;
++			if (root == NULL)
++				tmp = root = p;
++			else {
++				tmp->fts_link = p;
++				tmp = p;
++			}
++		}
++	}
++	if (compar && nitems > 1)
++		root = fts_sort(sp, root, nitems);
++
++	/*
++	 * Allocate a dummy pointer and make fts_read think that we've just
++	 * finished the node before the root(s); set p->fts_info to FTS_INIT
++	 * so that everything about the "current" node is ignored.
++	 */
++	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
++		goto mem3;
++	sp->fts_cur->fts_link = root;
++	sp->fts_cur->fts_info = FTS_INIT;
++
++	/*
++	 * If using chdir(2), grab a file descriptor pointing to dot to ensure
++	 * that we can get back here; this could be avoided for some paths,
++	 * but almost certainly not worth the effort.  Slashes, symbolic links,
++	 * and ".." are all fairly nasty problems.  Note, if we can't get the
++	 * descriptor we run anyway, just more slowly.
++	 */
++	if (!ISSET(FTS_NOCHDIR)
++	    && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
++		SET(FTS_NOCHDIR);
++
++	return (sp);
++
++mem3:	fts_lfree(root);
++	free(parent);
++mem2:	free(sp->fts_path);
++mem1:	free(sp);
++	return (NULL);
++}
++
++static void
++fts_load(FTS *sp, register FTSENT *p)
++{
++	register int len;
++	register char *cp;
++
++	/*
++	 * Load the stream structure for the next traversal.  Since we don't
++	 * actually enter the directory until after the preorder visit, set
++	 * the fts_accpath field specially so the chdir gets done to the right
++	 * place and the user can access the first node.  From fts_open it's
++	 * known that the path will fit.
++	 */
++	len = p->fts_pathlen = p->fts_namelen;
++	memmove(sp->fts_path, p->fts_name, len + 1);
++	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
++		len = strlen(++cp);
++		memmove(p->fts_name, cp, len + 1);
++		p->fts_namelen = len;
++	}
++	p->fts_accpath = p->fts_path = sp->fts_path;
++	sp->fts_dev = p->fts_dev;
++}
++
++int
++fts_close(FTS *sp)
++{
++	register FTSENT *freep, *p;
++	int saved_errno;
++
++	/*
++	 * This still works if we haven't read anything -- the dummy structure
++	 * points to the root list, so we step through to the end of the root
++	 * list which has a valid parent pointer.
++	 */
++	if (sp->fts_cur) {
++		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
++			freep = p;
++			p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
++			free(freep);
++		}
++		free(p);
++	}
++
++	/* Free up child linked list, sort array, path buffer. */
++	if (sp->fts_child)
++		fts_lfree(sp->fts_child);
++	free(sp->fts_array);
++	free(sp->fts_path);
++
++	/* Return to original directory, save errno if necessary. */
++	if (!ISSET(FTS_NOCHDIR)) {
++		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
++		(void)close(sp->fts_rfd);
++
++		/* Set errno and return. */
++		if (saved_errno != 0) {
++			/* Free up the stream pointer. */
++			free(sp);
++			errno = saved_errno;
++			return (-1);
++		}
++	}
++
++	/* Free up the stream pointer. */
++	free(sp);
++	return (0);
++}
++
++/*
++ * Special case of "/" at the end of the path so that slashes aren't
++ * appended which would cause paths to be written as "....//foo".
++ */
++#define	NAPPEND(p)							\
++	(p->fts_path[p->fts_pathlen - 1] == '/'				\
++	    ? p->fts_pathlen - 1 : p->fts_pathlen)
++
++FTSENT *
++fts_read(register FTS *sp)
++{
++	register FTSENT *p, *tmp;
++	register int instr;
++	register char *t;
++	int saved_errno;
++
++	/* If finished or unrecoverable error, return NULL. */
++	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
++		return (NULL);
++
++	/* Set current node pointer. */
++	p = sp->fts_cur;
++
++	/* Save and zero out user instructions. */
++	instr = p->fts_instr;
++	p->fts_instr = FTS_NOINSTR;
++
++	/* Any type of file may be re-visited; re-stat and re-turn. */
++	if (instr == FTS_AGAIN) {
++		p->fts_info = fts_stat(sp, p, 0);
++		return (p);
++	}
++
++	/*
++	 * Following a symlink -- SLNONE test allows application to see
++	 * SLNONE and recover.  If indirecting through a symlink, have
++	 * keep a pointer to current location.  If unable to get that
++	 * pointer, follow fails.
++	 */
++	if (instr == FTS_FOLLOW &&
++	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
++		p->fts_info = fts_stat(sp, p, 1);
++		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
++			if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
++				p->fts_errno = errno;
++				p->fts_info = FTS_ERR;
++			} else
++				p->fts_flags |= FTS_SYMFOLLOW;
++		}
++		return (p);
++	}
++
++	/* Directory in pre-order. */
++	if (p->fts_info == FTS_D) {
++		/* If skipped or crossed mount point, do post-order visit. */
++		if (instr == FTS_SKIP ||
++		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
++			if (p->fts_flags & FTS_SYMFOLLOW)
++				(void)close(p->fts_symfd);
++			if (sp->fts_child) {
++				fts_lfree(sp->fts_child);
++				sp->fts_child = NULL;
++			}
++			p->fts_info = FTS_DP;
++			return (p);
++		}
++
++		/* Rebuild if only read the names and now traversing. */
++		if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
++			CLR(FTS_NAMEONLY);
++			fts_lfree(sp->fts_child);
++			sp->fts_child = NULL;
++		}
++
++		/*
++		 * Cd to the subdirectory.
++		 *
++		 * If have already read and now fail to chdir, whack the list
++		 * to make the names come out right, and set the parent errno
++		 * so the application will eventually get an error condition.
++		 * Set the FTS_DONTCHDIR flag so that when we logically change
++		 * directories back to the parent we don't do a chdir.
++		 *
++		 * If haven't read do so.  If the read fails, fts_build sets
++		 * FTS_STOP or the fts_info field of the node.
++		 */
++		if (sp->fts_child != NULL) {
++			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
++				p->fts_errno = errno;
++				p->fts_flags |= FTS_DONTCHDIR;
++				for (p = sp->fts_child; p != NULL;
++				     p = p->fts_link)
++					p->fts_accpath =
++					    p->fts_parent->fts_accpath;
++			}
++		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
++			if (ISSET(FTS_STOP))
++				return (NULL);
++			return (p);
++		}
++		p = sp->fts_child;
++		sp->fts_child = NULL;
++		sp->fts_cur = p;
++		goto name;
++	}
++
++	/* Move to the next node on this level. */
++next:	tmp = p;
++	if ((p = p->fts_link) != NULL) {
++		sp->fts_cur = p;
++		free(tmp);
++
++		/*
++		 * If reached the top, return to the original directory (or
++		 * the root of the tree), and load the paths for the next root.
++		 */
++		if (p->fts_level == FTS_ROOTLEVEL) {
++			if (FCHDIR(sp, sp->fts_rfd)) {
++				SET(FTS_STOP);
++				return (NULL);
++			}
++			fts_load(sp, p);
++			return p;
++		}
++
++		/*
++		 * User may have called fts_set on the node.  If skipped,
++		 * ignore.  If followed, get a file descriptor so we can
++		 * get back if necessary.
++		 */
++		if (p->fts_instr == FTS_SKIP)
++			goto next;
++		if (p->fts_instr == FTS_FOLLOW) {
++			p->fts_info = fts_stat(sp, p, 1);
++			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
++				if ((p->fts_symfd =
++				    open(".", O_RDONLY, 0)) < 0) {
++					p->fts_errno = errno;
++					p->fts_info = FTS_ERR;
++				} else
++					p->fts_flags |= FTS_SYMFOLLOW;
++			}
++			p->fts_instr = FTS_NOINSTR;
++		}
++
++name:		t = sp->fts_path + NAPPEND(p->fts_parent);
++		*t++ = '/';
++		memmove(t, p->fts_name, p->fts_namelen + 1);
++		return p;
++	}
++
++	/* Move up to the parent node. */
++	p = tmp->fts_parent;
++	sp->fts_cur = p;
++	free(tmp);
++
++	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
++		/*
++		 * Done; free everything up and set errno to 0 so the user
++		 * can distinguish between error and EOF.
++		 */
++		free(p);
++		errno = 0;
++		return (sp->fts_cur = NULL);
++	}
++
++	/* NUL terminate the pathname. */
++	sp->fts_path[p->fts_pathlen] = '\0';
++
++	/*
++	 * Return to the parent directory.  If at a root node or came through
++	 * a symlink, go back through the file descriptor.  Otherwise, cd up
++	 * one directory.
++	 */
++	if (p->fts_level == FTS_ROOTLEVEL) {
++		if (FCHDIR(sp, sp->fts_rfd)) {
++			SET(FTS_STOP);
++			return (NULL);
++		}
++	} else if (p->fts_flags & FTS_SYMFOLLOW) {
++		if (FCHDIR(sp, p->fts_symfd)) {
++			saved_errno = errno;
++			(void)close(p->fts_symfd);
++			errno = saved_errno;
++			SET(FTS_STOP);
++			return (NULL);
++		}
++		(void)close(p->fts_symfd);
++	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
++		   fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
++		SET(FTS_STOP);
++		return (NULL);
++	}
++	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
++	return p;
++}
++
++/*
++ * Fts_set takes the stream as an argument although it's not used in this
++ * implementation; it would be necessary if anyone wanted to add global
++ * semantics to fts using fts_set.  An error return is allowed for similar
++ * reasons.
++ */
++/* ARGSUSED */
++int
++fts_set(FTS *sp, FTSENT *p, int instr)
++{
++	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
++	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
++		errno = EINVAL;
++		return (1);
++	}
++	p->fts_instr = instr;
++	return (0);
++}
++
++FTSENT *
++fts_children(register FTS *sp, int instr)
++{
++	register FTSENT *p;
++	int fd;
++
++	if (instr != 0 && instr != FTS_NAMEONLY) {
++		errno = EINVAL;
++		return (NULL);
++	}
++
++	/* Set current node pointer. */
++	p = sp->fts_cur;
++
++	/*
++	 * Errno set to 0 so user can distinguish empty directory from
++	 * an error.
++	 */
++	errno = 0;
++
++	/* Fatal errors stop here. */
++	if (ISSET(FTS_STOP))
++		return (NULL);
++
++	/* Return logical hierarchy of user's arguments. */
++	if (p->fts_info == FTS_INIT)
++		return (p->fts_link);
++
++	/*
++	 * If not a directory being visited in pre-order, stop here.  Could
++	 * allow FTS_DNR, assuming the user has fixed the problem, but the
++	 * same effect is available with FTS_AGAIN.
++	 */
++	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
++		return (NULL);
++
++	/* Free up any previous child list. */
++	if (sp->fts_child != NULL)
++		fts_lfree(sp->fts_child);
++
++	if (instr == FTS_NAMEONLY) {
++		SET(FTS_NAMEONLY);
++		instr = BNAMES;
++	} else
++		instr = BCHILD;
++
++	/*
++	 * If using chdir on a relative path and called BEFORE fts_read does
++	 * its chdir to the root of a traversal, we can lose -- we need to
++	 * chdir into the subdirectory, and we don't know where the current
++	 * directory is, so we can't get back so that the upcoming chdir by
++	 * fts_read will work.
++	 */
++	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
++	    ISSET(FTS_NOCHDIR))
++		return (sp->fts_child = fts_build(sp, instr));
++
++	if ((fd = open(".", O_RDONLY, 0)) < 0)
++		return (NULL);
++	sp->fts_child = fts_build(sp, instr);
++	if (fchdir(fd))
++		return (NULL);
++	(void)close(fd);
++	return (sp->fts_child);
++}
++
++/*
++ * This is the tricky part -- do not casually change *anything* in here.  The
++ * idea is to build the linked list of entries that are used by fts_children
++ * and fts_read.  There are lots of special cases.
++ *
++ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
++ * set and it's a physical walk (so that symbolic links can't be directories),
++ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
++ * of the file is in the directory entry.  Otherwise, we assume that the number
++ * of subdirectories in a node is equal to the number of links to the parent.
++ * The former skips all stat calls.  The latter skips stat calls in any leaf
++ * directories and for any files after the subdirectories in the directory have
++ * been found, cutting the stat calls by about 2/3.
++ */
++static FTSENT *
++fts_build(register FTS *sp, int type)
++{
++	register struct dirent *dp;
++	register FTSENT *p, *head;
++	register int nitems;
++	FTSENT *cur, *tail;
++	DIR *dirp;
++	void *oldaddr;
++	int cderrno, descend, len, level, nlinks, saved_errno,
++	    nostat, doadjust;
++	size_t maxlen;
++	char *cp;
++
++	/* Set current node pointer. */
++	cur = sp->fts_cur;
++
++	/*
++	 * Open the directory for reading.  If this fails, we're done.
++	 * If being called from fts_read, set the fts_info field.
++	 */
++#if defined FTS_WHITEOUT && 0
++	if (ISSET(FTS_WHITEOUT))
++		oflag = DTF_NODUP|DTF_REWIND;
++	else
++		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
++#else
++# define opendir2(path, flag) opendir(path)
++#endif
++       if ((dirp = opendir2(cur->fts_accpath, oflag)) == NULL) {
++		if (type == BREAD) {
++			cur->fts_info = FTS_DNR;
++			cur->fts_errno = errno;
++		}
++		return (NULL);
++	}
++
++	/*
++	 * Nlinks is the number of possible entries of type directory in the
++	 * directory if we're cheating on stat calls, 0 if we're not doing
++	 * any stat calls at all, -1 if we're doing stats on everything.
++	 */
++	if (type == BNAMES) {
++		nlinks = 0;
++		/* Be quiet about nostat, GCC. */
++		nostat = 0;
++	} else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
++		nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
++		nostat = 1;
++	} else {
++		nlinks = -1;
++		nostat = 0;
++	}
++
++#ifdef notdef
++	(void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
++	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
++	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
++#endif
++	/*
++	 * If we're going to need to stat anything or we want to descend
++	 * and stay in the directory, chdir.  If this fails we keep going,
++	 * but set a flag so we don't chdir after the post-order visit.
++	 * We won't be able to stat anything, but we can still return the
++	 * names themselves.  Note, that since fts_read won't be able to
++	 * chdir into the directory, it will have to return different path
++	 * names than before, i.e. "a/b" instead of "b".  Since the node
++	 * has already been visited in pre-order, have to wait until the
++	 * post-order visit to return the error.  There is a special case
++	 * here, if there was nothing to stat then it's not an error to
++	 * not be able to stat.  This is all fairly nasty.  If a program
++	 * needed sorted entries or stat information, they had better be
++	 * checking FTS_NS on the returned nodes.
++	 */
++	cderrno = 0;
++	if (nlinks || type == BREAD) {
++		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
++			if (nlinks && type == BREAD)
++				cur->fts_errno = errno;
++			cur->fts_flags |= FTS_DONTCHDIR;
++			descend = 0;
++			cderrno = errno;
++			(void)closedir(dirp);
++			dirp = NULL;
++		} else
++			descend = 1;
++	} else
++		descend = 0;
++
++	/*
++	 * Figure out the max file name length that can be stored in the
++	 * current path -- the inner loop allocates more path as necessary.
++	 * We really wouldn't have to do the maxlen calculations here, we
++	 * could do them in fts_read before returning the path, but it's a
++	 * lot easier here since the length is part of the dirent structure.
++	 *
++	 * If not changing directories set a pointer so that can just append
++	 * each new name into the path.
++	 */
++	len = NAPPEND(cur);
++	if (ISSET(FTS_NOCHDIR)) {
++		cp = sp->fts_path + len;
++		*cp++ = '/';
++	} else {
++		/* GCC, you're too verbose. */
++		cp = NULL;
++	}
++	len++;
++	maxlen = sp->fts_pathlen - len;
++
++	level = cur->fts_level + 1;
++
++	/* Read the directory, attaching each entry to the `link' pointer. */
++	doadjust = 0;
++	for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
++		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
++			continue;
++
++		if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL)
++			goto mem1;
++		if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
++			oldaddr = sp->fts_path;
++			if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
++				/*
++				 * No more memory for path or structures.  Save
++				 * errno, free up the current structure and the
++				 * structures already allocated.
++				 */
++mem1:				saved_errno = errno;
++				free(p);
++				fts_lfree(head);
++				(void)closedir(dirp);
++				cur->fts_info = FTS_ERR;
++				SET(FTS_STOP);
++				errno = saved_errno;
++				return (NULL);
++			}
++			/* Did realloc() change the pointer? */
++			if (oldaddr != sp->fts_path) {
++				doadjust = 1;
++				if (ISSET(FTS_NOCHDIR))
++					cp = sp->fts_path + len;
++			}
++			maxlen = sp->fts_pathlen - len;
++		}
++
++		if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) {
++			/*
++			 * In an FTSENT, fts_pathlen is a u_short so it is
++			 * possible to wraparound here.  If we do, free up
++			 * the current structure and the structures already
++			 * allocated, then error out with ENAMETOOLONG.
++			 */
++			free(p);
++			fts_lfree(head);
++			(void)closedir(dirp);
++			cur->fts_info = FTS_ERR;
++			SET(FTS_STOP);
++			errno = ENAMETOOLONG;
++			return (NULL);
++		}
++		p->fts_level = level;
++		p->fts_parent = sp->fts_cur;
++		p->fts_pathlen = len + _D_EXACT_NAMLEN (dp);
++
++#if defined FTS_WHITEOUT && 0
++		if (dp->d_type == DT_WHT)
++			p->fts_flags |= FTS_ISW;
++#endif
++
++#if 0
++		/* Unreachable code.  cderrno is only ever set to a nonnull
++		   value if dirp is closed at the same time.  But then we
++		   cannot enter this loop.  */
++		if (cderrno) {
++			if (nlinks) {
++				p->fts_info = FTS_NS;
++				p->fts_errno = cderrno;
++			} else
++				p->fts_info = FTS_NSOK;
++			p->fts_accpath = cur->fts_accpath;
++		} else
++#endif
++		if (nlinks == 0
++#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
++			   || (nostat &&
++			       dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
++#endif
++		    ) {
++			p->fts_accpath =
++			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
++			p->fts_info = FTS_NSOK;
++		} else {
++			/* Build a file name for fts_stat to stat. */
++			if (ISSET(FTS_NOCHDIR)) {
++				p->fts_accpath = p->fts_path;
++				memmove(cp, p->fts_name, p->fts_namelen + 1);
++			} else
++				p->fts_accpath = p->fts_name;
++			/* Stat it. */
++			p->fts_info = fts_stat(sp, p, 0);
++
++			/* Decrement link count if applicable. */
++			if (nlinks > 0 && (p->fts_info == FTS_D ||
++			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
++				--nlinks;
++		}
++
++		/* We walk in directory order so "ls -f" doesn't get upset. */
++		p->fts_link = NULL;
++		if (head == NULL)
++			head = tail = p;
++		else {
++			tail->fts_link = p;
++			tail = p;
++		}
++		++nitems;
++	}
++	if (dirp)
++		(void)closedir(dirp);
++
++	/*
++	 * If realloc() changed the address of the path, adjust the
++	 * addresses for the rest of the tree and the dir list.
++	 */
++	if (doadjust)
++		fts_padjust(sp, head);
++
++	/*
++	 * If not changing directories, reset the path back to original
++	 * state.
++	 */
++	if (ISSET(FTS_NOCHDIR)) {
++		if (len == sp->fts_pathlen || nitems == 0)
++			--cp;
++		*cp = '\0';
++	}
++
++	/*
++	 * If descended after called from fts_children or after called from
++	 * fts_read and nothing found, get back.  At the root level we use
++	 * the saved fd; if one of fts_open()'s arguments is a relative path
++	 * to an empty directory, we wind up here with no other way back.  If
++	 * can't get back, we're done.
++	 */
++	if (descend && (type == BCHILD || !nitems) &&
++	    (cur->fts_level == FTS_ROOTLEVEL ?
++	     FCHDIR(sp, sp->fts_rfd) :
++	     fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
++		cur->fts_info = FTS_ERR;
++		SET(FTS_STOP);
++		fts_lfree(head);
++		return (NULL);
++	}
++
++	/* If didn't find anything, return NULL. */
++	if (!nitems) {
++		if (type == BREAD)
++			cur->fts_info = FTS_DP;
++		fts_lfree(head);
++		return (NULL);
++	}
++
++	/* Sort the entries. */
++	if (sp->fts_compar && nitems > 1)
++		head = fts_sort(sp, head, nitems);
++	return (head);
++}
++
++static u_short
++fts_stat(FTS *sp, register FTSENT *p, int follow)
++{
++	register FTSENT *t;
++	register dev_t dev;
++	register ino_t ino;
++	struct stat *sbp, sb;
++	int saved_errno;
++
++	/* If user needs stat info, stat buffer already allocated. */
++	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
++
++#if defined FTS_WHITEOUT && 0
++	/* check for whiteout */
++	if (p->fts_flags & FTS_ISW) {
++		if (sbp != &sb) {
++			memset(sbp, '\0', sizeof (*sbp));
++			sbp->st_mode = S_IFWHT;
++		}
++		return (FTS_W);
++       }
++#endif
++
++	/*
++	 * If doing a logical walk, or application requested FTS_FOLLOW, do
++	 * a stat(2).  If that fails, check for a non-existent symlink.  If
++	 * fail, set the errno from the stat call.
++	 */
++	if (ISSET(FTS_LOGICAL) || follow) {
++		if (stat(p->fts_accpath, sbp)) {
++			saved_errno = errno;
++			if (!lstat(p->fts_accpath, sbp)) {
++				errno = 0;
++				return (FTS_SLNONE);
++			}
++			p->fts_errno = saved_errno;
++			goto err;
++		}
++	} else if (lstat(p->fts_accpath, sbp)) {
++		p->fts_errno = errno;
++err:		memset(sbp, 0, sizeof(struct stat));
++		return (FTS_NS);
++	}
++
++	if (S_ISDIR(sbp->st_mode)) {
++		/*
++		 * Set the device/inode.  Used to find cycles and check for
++		 * crossing mount points.  Also remember the link count, used
++		 * in fts_build to limit the number of stat calls.  It is
++		 * understood that these fields are only referenced if fts_info
++		 * is set to FTS_D.
++		 */
++		dev = p->fts_dev = sbp->st_dev;
++		ino = p->fts_ino = sbp->st_ino;
++		p->fts_nlink = sbp->st_nlink;
++
++		if (ISDOT(p->fts_name))
++			return (FTS_DOT);
++
++		/*
++		 * Cycle detection is done by brute force when the directory
++		 * is first encountered.  If the tree gets deep enough or the
++		 * number of symbolic links to directories is high enough,
++		 * something faster might be worthwhile.
++		 */
++		for (t = p->fts_parent;
++		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
++			if (ino == t->fts_ino && dev == t->fts_dev) {
++				p->fts_cycle = t;
++				return (FTS_DC);
++			}
++		return (FTS_D);
++	}
++	if (S_ISLNK(sbp->st_mode))
++		return (FTS_SL);
++	if (S_ISREG(sbp->st_mode))
++		return (FTS_F);
++	return (FTS_DEFAULT);
++}
++
++static FTSENT *
++fts_sort(FTS *sp, FTSENT *head, register int nitems)
++{
++	register FTSENT **ap, *p;
++
++	/*
++	 * Construct an array of pointers to the structures and call qsort(3).
++	 * Reassemble the array in the order returned by qsort.  If unable to
++	 * sort for memory reasons, return the directory entries in their
++	 * current order.  Allocate enough space for the current needs plus
++	 * 40 so don't realloc one entry at a time.
++	 */
++	if (nitems > sp->fts_nitems) {
++		struct _ftsent **a;
++
++		sp->fts_nitems = nitems + 40;
++		if ((a = realloc(sp->fts_array,
++ 		    (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
++			free(sp->fts_array);
++			sp->fts_array = NULL;
++			sp->fts_nitems = 0;
++			return (head);
++		}
++		sp->fts_array = a;
++	}
++	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
++		*ap++ = p;
++	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
++	for (head = *(ap = sp->fts_array); --nitems; ++ap)
++		ap[0]->fts_link = ap[1];
++	ap[0]->fts_link = NULL;
++	return (head);
++}
++
++static FTSENT *
++fts_alloc(FTS *sp, const char *name, size_t namelen)
++{
++	register FTSENT *p;
++	size_t len;
++
++	/*
++	 * The file name is a variable length array and no stat structure is
++	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
++	 * structure, the file name and the stat structure in one chunk, but
++	 * be careful that the stat structure is reasonably aligned.  Since the
++	 * fts_name field is declared to be of size 1, the fts_name pointer is
++	 * namelen + 2 before the first possible address of the stat structure.
++	 */
++	len = sizeof(FTSENT) + namelen;
++	if (!ISSET(FTS_NOSTAT))
++		len += sizeof(struct stat) + ALIGNBYTES;
++	if ((p = malloc(len)) == NULL)
++		return (NULL);
++
++	/* Copy the name and guarantee NUL termination. */
++	memmove(p->fts_name, name, namelen);
++	p->fts_name[namelen] = '\0';
++
++	if (!ISSET(FTS_NOSTAT))
++		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
++	p->fts_namelen = namelen;
++	p->fts_path = sp->fts_path;
++	p->fts_errno = 0;
++	p->fts_flags = 0;
++	p->fts_instr = FTS_NOINSTR;
++	p->fts_number = 0;
++	p->fts_pointer = NULL;
++	return (p);
++}
++
++static void
++fts_lfree(register FTSENT *head)
++{
++	register FTSENT *p;
++
++	/* Free a linked list of structures. */
++	while ((p = head)) {
++		head = head->fts_link;
++		free(p);
++	}
++}
++
++/*
++ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
++ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
++ * though the kernel won't resolve them.  Add the size (not just what's needed)
++ * plus 256 bytes so don't realloc the path 2 bytes at a time.
++ */
++static int
++fts_palloc(FTS *sp, size_t more)
++{
++	char *p;
++
++	sp->fts_pathlen += more + 256;
++	/*
++	 * Check for possible wraparound.  In an FTS, fts_pathlen is
++	 * a signed int but in an FTSENT it is an unsigned short.
++	 * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
++	 */
++	if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
++		free(sp->fts_path);
++		sp->fts_path = NULL;
++		errno = ENAMETOOLONG;
++		return (1);
++	}
++	p = realloc(sp->fts_path, sp->fts_pathlen);
++	if (p == NULL) {
++		free(sp->fts_path);
++		sp->fts_path = NULL;
++		return 1;
++	}
++	sp->fts_path = p;
++	return 0;
++}
++
++/*
++ * When the path is realloc'd, have to fix all of the pointers in structures
++ * already returned.
++ */
++static void
++fts_padjust(FTS *sp, FTSENT *head)
++{
++	FTSENT *p;
++	char *addr = sp->fts_path;
++
++#define	ADJUST(p) do {							\
++	if ((p)->fts_accpath != (p)->fts_name) {			\
++		(p)->fts_accpath =					\
++		    (char *)addr + ((p)->fts_accpath - (p)->fts_path);	\
++	}								\
++	(p)->fts_path = addr;						\
++} while (0)
++	/* Adjust the current set of children. */
++	for (p = sp->fts_child; p; p = p->fts_link)
++		ADJUST(p);
++
++	/* Adjust the rest of the tree, including the current level. */
++	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
++		ADJUST(p);
++		p = p->fts_link ? p->fts_link : p->fts_parent;
++	}
++}
++
++static size_t
++fts_maxarglen(char * const *argv)
++{
++	size_t len, max;
++
++	for (max = 0; *argv; ++argv)
++		if ((len = strlen(*argv)) > max)
++			max = len;
++	return (max + 1);
++}
++
++/*
++ * Change to dir specified by fd or p->fts_accpath without getting
++ * tricked by someone changing the world out from underneath us.
++ * Assumes p->fts_dev and p->fts_ino are filled in.
++ */
++static int
++fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path)
++{
++	int ret, oerrno, newfd;
++	struct stat64 sb;
++
++	newfd = fd;
++	if (ISSET(FTS_NOCHDIR))
++		return (0);
++	if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
++		return (-1);
++	if (fstat64(newfd, &sb)) {
++		ret = -1;
++		goto bail;
++	}
++	if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
++		errno = ENOENT;		/* disinformation */
++		ret = -1;
++		goto bail;
++	}
++	ret = fchdir(newfd);
++bail:
++	oerrno = errno;
++	if (fd < 0)
++		(void)close(newfd);
++	errno = oerrno;
++	return (ret);
++}
+Index: b/libdwfl/fts_.h
+===================================================================
+--- /dev/null
++++ b/libdwfl/fts_.h
+@@ -0,0 +1,131 @@
++/*
++ * Copyright (c) 1989, 1993
++ *	The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *	@(#)fts.h	8.3 (Berkeley) 8/14/94
++ */
++
++#ifndef	_FTS_H
++#define	_FTS_H 1
++
++#include <features.h>
++#include <sys/types.h>
++
++/* The fts interface is incompatible with the LFS interface which
++   transparently uses the 64-bit file access functions.  */
++#ifdef __USE_FILE_OFFSET64
++# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
++#endif
++
++
++typedef struct {
++	struct _ftsent *fts_cur;	/* current node */
++	struct _ftsent *fts_child;	/* linked list of children */
++	struct _ftsent **fts_array;	/* sort array */
++	dev_t fts_dev;			/* starting device # */
++	char *fts_path;			/* path for this descent */
++	int fts_rfd;			/* fd for root */
++	int fts_pathlen;		/* sizeof(path) */
++	int fts_nitems;			/* elements in the sort array */
++	int (*fts_compar) (const void *, const void *); /* compare fn */
++
++#define	FTS_COMFOLLOW	0x0001		/* follow command line symlinks */
++#define	FTS_LOGICAL	0x0002		/* logical walk */
++#define	FTS_NOCHDIR	0x0004		/* don't change directories */
++#define	FTS_NOSTAT	0x0008		/* don't get stat info */
++#define	FTS_PHYSICAL	0x0010		/* physical walk */
++#define	FTS_SEEDOT	0x0020		/* return dot and dot-dot */
++#define	FTS_XDEV	0x0040		/* don't cross devices */
++#define FTS_WHITEOUT	0x0080		/* return whiteout information */
++#define	FTS_OPTIONMASK	0x00ff		/* valid user option mask */
++
++#define	FTS_NAMEONLY	0x0100		/* (private) child names only */
++#define	FTS_STOP	0x0200		/* (private) unrecoverable error */
++	int fts_options;		/* fts_open options, global flags */
++} FTS;
++
++typedef struct _ftsent {
++	struct _ftsent *fts_cycle;	/* cycle node */
++	struct _ftsent *fts_parent;	/* parent directory */
++	struct _ftsent *fts_link;	/* next file in directory */
++	long fts_number;	        /* local numeric value */
++	void *fts_pointer;	        /* local address value */
++	char *fts_accpath;		/* access path */
++	char *fts_path;			/* root path */
++	int fts_errno;			/* errno for this node */
++	int fts_symfd;			/* fd for symlink */
++	u_short fts_pathlen;		/* strlen(fts_path) */
++	u_short fts_namelen;		/* strlen(fts_name) */
++
++	ino_t fts_ino;			/* inode */
++	dev_t fts_dev;			/* device */
++	nlink_t fts_nlink;		/* link count */
++
++#define	FTS_ROOTPARENTLEVEL	-1
++#define	FTS_ROOTLEVEL		 0
++	short fts_level;		/* depth (-1 to N) */
++
++#define	FTS_D		 1		/* preorder directory */
++#define	FTS_DC		 2		/* directory that causes cycles */
++#define	FTS_DEFAULT	 3		/* none of the above */
++#define	FTS_DNR		 4		/* unreadable directory */
++#define	FTS_DOT		 5		/* dot or dot-dot */
++#define	FTS_DP		 6		/* postorder directory */
++#define	FTS_ERR		 7		/* error; errno is set */
++#define	FTS_F		 8		/* regular file */
++#define	FTS_INIT	 9		/* initialized only */
++#define	FTS_NS		10		/* stat(2) failed */
++#define	FTS_NSOK	11		/* no stat(2) requested */
++#define	FTS_SL		12		/* symbolic link */
++#define	FTS_SLNONE	13		/* symbolic link without target */
++#define FTS_W		14		/* whiteout object */
++	u_short fts_info;		/* user flags for FTSENT structure */
++
++#define	FTS_DONTCHDIR	 0x01		/* don't chdir .. to the parent */
++#define	FTS_SYMFOLLOW	 0x02		/* followed a symlink to get here */
++	u_short fts_flags;		/* private flags for FTSENT structure */
++
++#define	FTS_AGAIN	 1		/* read node again */
++#define	FTS_FOLLOW	 2		/* follow symbolic link */
++#define	FTS_NOINSTR	 3		/* no instructions */
++#define	FTS_SKIP	 4		/* discard node */
++	u_short fts_instr;		/* fts_set() instructions */
++
++	struct stat *fts_statp;		/* stat(2) information */
++	char fts_name[1];		/* file name */
++} FTSENT;
++
++__BEGIN_DECLS
++FTSENT	*fts_children (FTS *, int);
++int	 fts_close (FTS *);
++FTS	*fts_open (char * const *, int,
++		   int (*)(const FTSENT **, const FTSENT **));
++FTSENT	*fts_read (FTS *);
++int	 fts_set (FTS *, FTSENT *, int) __THROW;
++__END_DECLS
++
++#endif /* fts.h */
+Index: b/libdwfl/linux-kernel-modules.c
+===================================================================
+--- a/libdwfl/linux-kernel-modules.c
++++ b/libdwfl/linux-kernel-modules.c
+@@ -29,7 +29,11 @@
+ /* We include this before config.h because it can't handle _FILE_OFFSET_BITS.
+    Everything we need here is fine if its declarations just come first.  */
+ 
++#ifdef HAVE_FTS_H
+ #include <fts.h>
++#else
++#include "fts_.h"
++#endif
+ 
+ #include <config.h>
+ 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 14/15] elfutils: towards uClibc support: disable po build
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (12 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 13/15] elfutils: towards uClibc support: FTS functions Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-06 15:22 ` [Buildroot] [PATCH 15/15] elfutils: make available on uClibc toolchains Thomas Petazzoni
  2013-01-07 22:32 ` [Buildroot] [pull request] Pull request for branch perf-elfutils Peter Korsgaard
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

Building the po/ directory complains that the scripts in there have
been generated with gettext 0.17, while we use gettext 0.18 in
Buildroot. Since we don't care that much about po files anyway, just
disable the build of this directory.

Heavily based from work done by Stefan Fr?berg, but with many further
modifications by Thomas Petazzoni.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/elfutils-05-disable-po.patch |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 package/elfutils/elfutils-05-disable-po.patch

diff --git a/package/elfutils/elfutils-05-disable-po.patch b/package/elfutils/elfutils-05-disable-po.patch
new file mode 100644
index 0000000..d98da0b
--- /dev/null
+++ b/package/elfutils/elfutils-05-disable-po.patch
@@ -0,0 +1,22 @@
+Disable the build of the po/ directory
+
+Building the po/ directory complains that the scripts in there have
+been generated with gettext 0.17, while we use gettext 0.18 in
+Buildroot. Since we don't care that much about po files anyway, just
+disable the build of this directory.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/Makefile.am
+===================================================================
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -28,7 +28,7 @@
+ 
+ # Add doc back when we have some real content.
+ SUBDIRS = config m4 lib libelf libebl libdwfl libdw libcpu libasm backends \
+-	  $(PROGS_SUBDIR) po tests
++	  $(PROGS_SUBDIR) tests
+ 
+ EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
+ 	     COPYING COPYING-GPLV2 COPYING-LGPLV3
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [PATCH 15/15] elfutils: make available on uClibc toolchains
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (13 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 14/15] elfutils: towards uClibc support: disable po build Thomas Petazzoni
@ 2013-01-06 15:22 ` Thomas Petazzoni
  2013-01-07 22:32 ` [Buildroot] [pull request] Pull request for branch perf-elfutils Peter Korsgaard
  15 siblings, 0 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-06 15:22 UTC (permalink / raw)
  To: buildroot

We finally have all the pieces needed to allow the build of elfutils
on uClibc. Only the libraries can be built, the programs remain
available only for glibc/eglibc toolchains.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/elfutils/Config.in |   11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/package/elfutils/Config.in b/package/elfutils/Config.in
index 78d02a5..b107a97 100644
--- a/package/elfutils/Config.in
+++ b/package/elfutils/Config.in
@@ -1,13 +1,5 @@
-comment "elfutils requires a glibc toolchain"
-	depends on !(BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
-		     BR2_TOOLCHAIN_CTNG_glibc     || \
-		     BR2_TOOLCHAIN_CTNG_eglibc)
-
 config BR2_PACKAGE_ELFUTILS
 	bool "elfutils"
-	depends on BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
-		   BR2_TOOLCHAIN_CTNG_glibc     || \
-		   BR2_TOOLCHAIN_CTNG_eglibc
 	select BR2_PACKAGE_ARGP_STANDALONE if \
 	       BR2_TOOLCHAIN_BUILDROOT   || \
 	       BR2_TOOLCHAIN_CTNG_uClibc || \
@@ -27,6 +19,9 @@ if BR2_PACKAGE_ELFUTILS
 
 config BR2_PACKAGE_ELFUTILS_PROGS
 	bool "Install programs"
+	depends on BR2_TOOLCHAIN_EXTERNAL_GLIBC || \
+		   BR2_TOOLCHAIN_CTNG_glibc     || \
+		   BR2_TOOLCHAIN_CTNG_eglibc
 	help
 	  This option tells elfutils to not only install the libelf
 	  libraries, but also the elfutils programs.
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Buildroot] [pull request] Pull request for branch perf-elfutils
  2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
                   ` (14 preceding siblings ...)
  2013-01-06 15:22 ` [Buildroot] [PATCH 15/15] elfutils: make available on uClibc toolchains Thomas Petazzoni
@ 2013-01-07 22:32 ` Peter Korsgaard
  2013-01-07 22:39   ` Thomas Petazzoni
  15 siblings, 1 reply; 19+ messages in thread
From: Peter Korsgaard @ 2013-01-07 22:32 UTC (permalink / raw)
  To: buildroot

>>>>> "Thomas" == Thomas Petazzoni <thomas.petazzoni@free-electrons.com> writes:

 Thomas> Hello,
 Thomas> Here is a set of patches that add the elfutils and perf packages in
 Thomas> Buildroot, based on previous efforts from Stefan Fr?berg and Kaiwan
 Thomas> Billimoria (thanks !).

 Thomas> These packages are not trivial because:
 Thomas>  1) perf is part of the kernel sources
 Thomas>  2) elfutils is a nightmare to build against uClibc

 Thomas> I've been working on this for about two days, trying different
 Thomas> solutions, the one proposed here appeared to be the most reasonable
 Thomas> one in terms of patch size, and maintenability.

Thanks everyone, committed series.

Thomas, please don't forget to (try to) send these patches upstream so
we don't have to maintain them ourselves in the future.

-- 
Bye, Peter Korsgaard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Buildroot] [pull request] Pull request for branch perf-elfutils
  2013-01-07 22:32 ` [Buildroot] [pull request] Pull request for branch perf-elfutils Peter Korsgaard
@ 2013-01-07 22:39   ` Thomas Petazzoni
  2013-01-08  7:18     ` Peter Korsgaard
  0 siblings, 1 reply; 19+ messages in thread
From: Thomas Petazzoni @ 2013-01-07 22:39 UTC (permalink / raw)
  To: buildroot

Dear Peter Korsgaard,

On Mon, 07 Jan 2013 23:32:56 +0100, Peter Korsgaard wrote:

> Thanks everyone, committed series.

Thanks for merging them. Hopefully, it won't make the autobuilders
explode too much.

> Thomas, please don't forget to (try to) send these patches upstream so
> we don't have to maintain them ourselves in the future.

Which ones exactly? The big fat patches we are downloading from
fedorahosted.org? Our patches?

All our patches are really specific to uClibc support, and seeing the
number of glibc-isms in elfutils, I am not sure the maintainers will be
interested in making it uClibc friendly. But it's maybe worth trying.

One nice thing that could be done is migrate the linux-kernel-module.c
thing to use nftw(), so we could drop the fts() mess.

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Buildroot] [pull request] Pull request for branch perf-elfutils
  2013-01-07 22:39   ` Thomas Petazzoni
@ 2013-01-08  7:18     ` Peter Korsgaard
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Korsgaard @ 2013-01-08  7:18 UTC (permalink / raw)
  To: buildroot

>>>>> "Thomas" == Thomas Petazzoni <thomas.petazzoni@free-electrons.com> writes:

Hi,

 >> Thomas, please don't forget to (try to) send these patches upstream so
 >> we don't have to maintain them ourselves in the future.

 Thomas> Which ones exactly? The big fat patches we are downloading from
 Thomas> fedorahosted.org? Our patches?

 Thomas> All our patches are really specific to uClibc support, and
 Thomas> seeing the number of glibc-isms in elfutils, I am not sure the
 Thomas> maintainers will be interested in making it uClibc
 Thomas> friendly. But it's maybe worth trying.

Our own. I would certainly say it's worth a try.

 Thomas> One nice thing that could be done is migrate the
 Thomas> linux-kernel-module.c thing to use nftw(), so we could drop the
 Thomas> fts() mess.

Indeed.

-- 
Bye, Peter Korsgaard

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2013-01-08  7:18 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-06 15:22 [Buildroot] [pull request] Pull request for branch perf-elfutils Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 01/15] package: support multiple patches Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 02/15] docs/manual: update to mention the multiple patches support Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 03/15] elfutils: new package Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 04/15] elfutils: make it possible to only install the libraries Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 05/15] perf: new package Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 06/15] perf: allow build against libelf when available Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 07/15] perf: add kernel version checks Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 08/15] argp-standlone: build position independent code Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 09/15] elfutils: towards uClibc support: argp-standalone usage Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 10/15] elfutils: towards uClibc support: solve memcpy problem Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 11/15] elfutils: towards uClibc support: requires largefile Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 12/15] elfutils: towards uClibc support: gettext Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 13/15] elfutils: towards uClibc support: FTS functions Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 14/15] elfutils: towards uClibc support: disable po build Thomas Petazzoni
2013-01-06 15:22 ` [Buildroot] [PATCH 15/15] elfutils: make available on uClibc toolchains Thomas Petazzoni
2013-01-07 22:32 ` [Buildroot] [pull request] Pull request for branch perf-elfutils Peter Korsgaard
2013-01-07 22:39   ` Thomas Petazzoni
2013-01-08  7:18     ` Peter Korsgaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox