Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Apr 2019 19:55:48 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r346582 - head/usr.bin/ar
Message-ID:  <201904221955.x3MJtmAm016884@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Mon Apr 22 19:55:47 2019
New Revision: 346582
URL: https://svnweb.freebsd.org/changeset/base/346582

Log:
  ar: shuffle symbol offsets during conversion for 32-bit ar archives
  
  During processing we maintain symbol offsets in the 64-bit s_so array,
  and when writing the archive convert to 32-bit if no offsets are greater
  than 4GB.  However, this was somewhat inefficient as we looped over the
  array twice: first, converting to big endian and second, writing each
  32-bit value one at a time (and incorrectly so on big-endian platforms).
  
  Instead, when writing a 32-bit archive shuffle convert symbol data to
  big endian (as required by the ar format) and shuffle to the beginning
  of the allocation at the same time.
  
  Also correct emission of the symbol count on big endian platforms.
  
  Further changes are planned, but this should fix powerpc64.
  
  Reported by:	jhibbits, mlinimon
  Reviewed by:	jhibbits, Gerald Aryeetey (earlier)
  Tested by:	jhibbits
  MFC after:	10 days
  MFC with:	r346079
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D20007

Modified:
  head/usr.bin/ar/write.c

Modified: head/usr.bin/ar/write.c
==============================================================================
--- head/usr.bin/ar/write.c	Mon Apr 22 19:36:19 2019	(r346581)
+++ head/usr.bin/ar/write.c	Mon Apr 22 19:55:47 2019	(r346582)
@@ -616,6 +616,7 @@ write_objs(struct bsdar *bsdar)
 	size_t pm_sz;		/* size of pseudo members */
 	size_t w_sz;		/* size of words in symbol table */
 	uint64_t		 nr;
+	uint32_t		 nr32;
 	int			 i;
 
 	if (elf_version(EV_CURRENT) == EV_NONE)
@@ -669,15 +670,18 @@ write_objs(struct bsdar *bsdar)
 			s_sz = (bsdar->s_cnt + 1) * sizeof(uint64_t) +
 			    bsdar->s_sn_sz;
 			pm_sz += s_sz;
-		}
-
-		for (i = 0; (size_t)i < bsdar->s_cnt; i++) {
-			if (w_sz == sizeof(uint32_t))
+			/* Convert to big-endian. */
+			for (i = 0; (size_t)i < bsdar->s_cnt; i++)
 				bsdar->s_so[i] =
-				    htobe32(bsdar->s_so[i] + pm_sz);
-			else
-				bsdar->s_so[i] =
 				    htobe64(bsdar->s_so[i] + pm_sz);
+		} else {
+			/*
+			 * Convert to big-endian and shuffle in-place to
+			 * the front of the allocation. XXX UB
+			 */
+			for (i = 0; (size_t)i < bsdar->s_cnt; i++)
+				((uint32_t *)(bsdar->s_so))[i] =
+				    htobe32(bsdar->s_so[i] + pm_sz);
 		}
 	}
 
@@ -708,19 +712,14 @@ write_objs(struct bsdar *bsdar)
 		archive_entry_set_size(entry, (bsdar->s_cnt + 1) * w_sz +
 		    bsdar->s_sn_sz);
 		AC(archive_write_header(a, entry));
-		if (w_sz == sizeof(uint32_t))
-			nr = (uint64_t)htobe32((uint32_t)bsdar->s_cnt);
-		else
+		if (w_sz == sizeof(uint64_t)) {
 			nr = htobe64(bsdar->s_cnt);
-		write_data(bsdar, a, &nr, w_sz);
-		if (w_sz == sizeof(uint64_t))
-			write_data(bsdar, a, bsdar->s_so, sizeof(uint64_t) *
-			    bsdar->s_cnt);
-		else
-			for (i = 0; (size_t)i < bsdar->s_cnt; i++)
-				write_data(bsdar, a,
-				    (uint32_t *)&bsdar->s_so[i],
-				    sizeof(uint32_t));
+			write_data(bsdar, a, &nr, sizeof(nr));
+		} else {
+			nr32 = htobe32((uint32_t)bsdar->s_cnt);
+			write_data(bsdar, a, &nr32, sizeof(nr32));
+		}
+		write_data(bsdar, a, bsdar->s_so, w_sz * bsdar->s_cnt);
 		write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
 		archive_entry_free(entry);
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904221955.x3MJtmAm016884>