RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: rpm-4_5: rpm/ CHANGES rpm/tools/ Makefile.am debugedit.c

From: Jeff Johnson <jbj@rpm5.org>
Date: Tue 28 Aug 2007 - 18:10:19 CEST
Message-Id: <20070828161019.A676734845B@rpm5.org>
  RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  jbj@rpm5.org
  Module: rpm                              Date:   28-Aug-2007 18:10:19
  Branch: rpm-4_5                          Handle: 2007082817101801

  Modified files:           (Branch: rpm-4_5)
    rpm                     CHANGES
    rpm/tools               Makefile.am debugedit.c

  Log:
    - update debugedit to include buildid changes.

  Summary:
    Revision    Changes     Path
    1.1360.2.35 +1  -0      rpm/CHANGES
    2.85.2.2    +4  -1      rpm/tools/Makefile.am
    2.9.2.1     +171 -5     rpm/tools/debugedit.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/CHANGES
  ============================================================================
  $ cvs diff -u -r1.1360.2.34 -r1.1360.2.35 CHANGES
  --- rpm/CHANGES	28 Aug 2007 00:44:41 -0000	1.1360.2.34
  +++ rpm/CHANGES	28 Aug 2007 16:10:18 -0000	1.1360.2.35
  @@ -1,4 +1,5 @@
   4.4.9 -> 4.5:
  +    - jbj: update debugedit to include buildid changes.
       - jbj: update id.po (Translation Project).
       - jbj: prepare for open as a macro in bleeding edge glibc-2.6.90+.
       - jbj: python: backport signalsCaught, remove archscore.
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/tools/Makefile.am
  ============================================================================
  $ cvs diff -u -r2.85.2.1 -r2.85.2.2 Makefile.am
  --- rpm/tools/Makefile.am	17 Jun 2007 01:11:49 -0000	2.85.2.1
  +++ rpm/tools/Makefile.am	28 Aug 2007 16:10:19 -0000	2.85.2.2
  @@ -28,7 +28,10 @@
   convertdb1_SOURCES =	convertdb1.c
   
   debugedit_SOURCES =	debugedit.c hashtab.c
  -debugedit_LDADD =	@WITH_LIBELF_LIB@ @WITH_POPT_LIB@
  +debugedit_LDADD =	\
  +	@WITH_LIBELF_LIB@\
  +	@WITH_BEECRYPT_LIB@\
  +	@WITH_POPT_LIB@
   
   rpmdeps_SOURCES =	rpmdeps.c
   
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/tools/debugedit.c
  ============================================================================
  $ cvs diff -u -r2.9 -r2.9.2.1 debugedit.c
  --- rpm/tools/debugedit.c	25 May 2007 17:36:41 -0000	2.9
  +++ rpm/tools/debugedit.c	28 Aug 2007 16:10:19 -0000	2.9.2.1
  @@ -1,4 +1,4 @@
  -/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc.
  +/* Copyright (C) 2001, 2002, 2003, 2005, 2007 Red Hat, Inc.
      Written by Alexander Larsson <alexl@redhat.com>, 2002
      Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
   
  @@ -35,7 +35,7 @@
   
   #include <gelf.h>
   
  -#if 0		/* XXX compile without dwarf.h */
  +#if 1		/* XXX compile without dwarf.h */
   #include <dwarf.h>
   #else
   /* some defines taken from the dwarf standard */
  @@ -69,6 +69,7 @@
   #define DW_FORM_indirect	0x16
   #endif
   
  +#include "beecrypt.h"
   #include "hashtab.h"
   
   #define DW_TAG_partial_unit 0x3c
  @@ -76,7 +77,8 @@
   char *base_dir = NULL;
   char *dest_dir = NULL;
   char *list_file = NULL;
  -int list_file_fd = -1; 
  +int list_file_fd = -1;
  +int do_build_id = 0;
   
   typedef unsigned int uint_32;
   typedef unsigned short uint_16;
  @@ -646,6 +648,7 @@
   	}
         else
   	ptr = srcptr = dir;
  +      unsigned char *srcstart=srcptr;
         while (*srcptr != 0)
   	{
   	  size_t len = strlen (srcptr) + 1;
  @@ -1249,6 +1252,8 @@
         "directory to rewrite base-dir into", NULL },
       { "list-file",  'l', POPT_ARG_STRING, &list_file, 0,
         "file where to put list of source and header file names", NULL },
  +    { "build-id",  'i', POPT_ARG_NONE, &do_build_id, 0,
  +      "recompute build ID note and print ID on stdout", NULL },
         POPT_AUTOHELP
       { NULL, 0, 0, NULL, 0, NULL, NULL }
   };
  @@ -1327,6 +1332,126 @@
     return NULL;
   }
   
  +/* Compute a fresh build ID bit-string from the editted file contents.  */
  +static void
  +handle_build_id (DSO *dso, Elf_Data *build_id,
  +		 size_t build_id_offset, size_t build_id_size)
  +{
  +  hashFunctionContext ctx;
  +  const hashFunction *hf = NULL;
  +  int i = hashFunctionCount ();
  +
  +  while (i-- > 0)
  +    {
  +      hf = hashFunctionGet (i);
  +      if (hf != NULL && hf->digestsize == build_id_size)
  +	break;
  +    }
  +  if (hf == NULL)
  +    {
  +      fprintf (stderr, "Cannot handle %Zu-byte build ID\n", build_id_size);
  +      exit (1);
  +    }
  +
  +  if (elf_update (dso->elf, ELF_C_NULL) < 0)
  +    {
  +      fprintf (stderr, "Failed to update file: %s\n",
  +	       elf_errmsg (elf_errno ()));
  +      exit (1);
  +    }
  +
  +  /* Clear the old bits so they do not affect the new hash.  */
  +  memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size);
  +
  +  hashFunctionContextInit (&ctx, hf);
  +
  +  /* Slurp the relevant header bits and section contents and feed them
  +     into the hash function.  The only bits we ignore are the offset
  +     fields in ehdr and shdrs, since the semantically identical ELF file
  +     could be written differently if it doesn't change the phdr layout.
  +     We always use the GElf (i.e. Elf64) formats for the bits to hash
  +     since it is convenient.  It doesn't matter whether this is an Elf32
  +     or Elf64 object, only that we are consistent in what bits feed the
  +     hash so it comes out the same for the same file contents.  */
  +  {
  +    inline void process (const void *data, size_t size);
  +    inline void process (const void *data, size_t size)
  +    {
  +      memchunk chunk = { .data = (void *) data, .size = size };
  +      hashFunctionContextUpdateMC (&ctx, &chunk);
  +    }
  +
  +    union
  +    {
  +      GElf_Ehdr ehdr;
  +      GElf_Phdr phdr;
  +      GElf_Shdr shdr;
  +    } u;
  +    Elf_Data x = { .d_version = EV_CURRENT, .d_buf = &u };
  +
  +    x.d_type = ELF_T_EHDR;
  +    x.d_size = sizeof u.ehdr;
  +    u.ehdr = dso->ehdr;
  +    u.ehdr.e_phoff = u.ehdr.e_shoff = 0;
  +    if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
  +      {
  +      bad:
  +	fprintf (stderr, "Failed to compute header checksum: %s\n",
  +		 elf_errmsg (elf_errno ()));
  +	exit (1);
  +      }
  +
  +    x.d_type = ELF_T_PHDR;
  +    x.d_size = sizeof u.phdr;
  +    for (i = 0; i < dso->ehdr.e_phnum; ++i)
  +      {
  +	if (gelf_getphdr (dso->elf, i, &u.phdr) == NULL)
  +	  goto bad;
  +	if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
  +	  goto bad;
  +	process (x.d_buf, x.d_size);
  +      }
  +
  +    x.d_type = ELF_T_SHDR;
  +    x.d_size = sizeof u.shdr;
  +    for (i = 0; i < dso->ehdr.e_shnum; ++i)
  +      if (dso->scn[i] != NULL)
  +	{
  +	  u.shdr = dso->shdr[i];
  +	  u.shdr.sh_offset = 0;
  +	  if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
  +	    goto bad;
  +	  process (x.d_buf, x.d_size);
  +
  +	  if (u.shdr.sh_type != SHT_NOBITS)
  +	    {
  +	      Elf_Data *d = elf_rawdata (dso->scn[i], NULL);
  +	      if (d == NULL)
  +		goto bad;
  +	      process (d->d_buf, d->d_size);
  +	    }
  +	}
  +  }
  +
  +  hashFunctionContextDigest (&ctx, (byte *) build_id->d_buf + build_id_offset);
  +  hashFunctionContextFree (&ctx);
  +
  +  elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY);
  +
  +  /* Now format the build ID bits in hex to print out.  */
  +  {
  +    const unsigned char * id = build_id->d_buf + build_id_offset;
  +    char hex[build_id_size * 2 + 1];
  +    int n = snprintf (hex, 3, "%02" PRIx8, id[0]);
  +    assert (n == 2);
  +    for (i = 1; i < build_id_size; ++i)
  +      {
  +	n = snprintf (&hex[i * 2], 3, "%02" PRIx8, id[i]);
  +	assert (n == 2);
  +      }
  +    puts (hex);
  +  }
  +}
   
   int
   main (int argc, char *argv[])
  @@ -1339,7 +1464,9 @@
     const char **args;
     struct stat stat_buf;
     char *p;
  -  
  +  Elf_Data *build_id = NULL;
  +  size_t build_id_offset = 0, build_id_size = 0;
  +
     optCon = poptGetContext("debugedit", argc, (const char **)argv,
   			  optionsTable, 0);
     
  @@ -1442,13 +1569,52 @@
   #endif
   	  if (strcmp (name, ".debug_info") == 0)
   	    edit_dwarf2 (dso);
  -	  
  +
  +	  break;
  +	case SHT_NOTE:
  +	  if (do_build_id
  +	      && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC))
  +	    {
  +	      /* Look for a build-ID note here.  */
  +	      Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL);
  +	      Elf32_Nhdr nh;
  +	      Elf_Data dst =
  +		{
  +		  .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
  +		  .d_buf = &nh, .d_size = sizeof nh
  +		};
  +	      Elf_Data src = dst;
  +	      src.d_buf = data->d_buf;
  +	      assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
  +	      while (data->d_buf + data->d_size - src.d_buf > (int) sizeof nh
  +		     && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA]))
  +		{
  +		  Elf32_Word len = sizeof nh + nh.n_namesz;
  +		  len = (len + 3) & ~3;
  +
  +		  if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
  +		      && !memcmp (src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
  +		    {
  +		      build_id = data;
  +		      build_id_offset = src.d_buf + len - data->d_buf;
  +		      build_id_size = nh.n_descsz;
  +		      break;
  +		    }
  +
  +		  len += nh.n_descsz;
  +		  len = (len + 3) & ~3;
  +		  src.d_buf += len;
  +		}
  +	    }
   	  break;
   	default:
   	  break;
   	}
       }
   
  +  if (do_build_id && build_id != NULL)
  +    handle_build_id (dso, build_id, build_id_offset, build_id_size);
  +
     if (elf_update (dso->elf, ELF_C_WRITE) < 0)
       {
         fprintf (stderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
  @@ .
Received on Tue Aug 28 18:10:19 2007
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.