diff --git a/include/ChangeLog b/include/ChangeLog
index e4aad2ba993b2fd2928ca7dc34cd5b63325382fb..c7c271b1ca9570e7f24188f69ba7d1adfef77abf 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,10 @@
+2003-05-15  Jim Blandy  <jimb@redhat.com>
+
+	* libiberty.h (hex_value): Make the value an unsigned int, to
+	avoid unexpected sign-extension when cast to unsigned types larger
+	than int --- like bfd_vma, on some platforms.
+	(_hex_value): Update declaration.
+
 2003-05-07  Jason Merrill  <jason@redhat.com>
 
 	* hashtab.h (iterative_hash): Prototype.
diff --git a/include/libiberty.h b/include/libiberty.h
index 676ceaba4a9cdc0f8d0351b389cf2ba3d308d2e4..761b2cf060ff5a33f4cfe7229099b85ef55351c9 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -254,12 +254,12 @@ extern double physmem_available PARAMS ((void));
 
 #define _hex_array_size 256
 #define _hex_bad	99
-extern const char _hex_value[_hex_array_size];
+extern const unsigned char _hex_value[_hex_array_size];
 extern void hex_init PARAMS ((void));
 #define hex_p(c)	(hex_value (c) != _hex_bad)
 /* If you change this, note well: Some code relies on side effects in
    the argument being performed exactly once.  */
-#define hex_value(c)	(_hex_value[(unsigned char) (c)])
+#define hex_value(c)	((unsigned int) _hex_value[(unsigned char) (c)])
 
 /* Definitions used by the pexecute routine.  */
 
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 066980339bac58e5f777406ef1cc59e83e77aa06..d30c591d24720f396f5545e52fbbe258cb93bea6 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,12 @@
+2003-05-15  Jim Blandy  <jimb@redhat.com>
+
+	* hex.c (_hex_value): Make this unsigned.
+	(hex_value): Update documentation for new return type.  hex_value
+	now expands to an unsigned int expression, to avoid unexpected
+	sign extension when we store it in a bfd_vma, which is larger than
+	int on some platforms.
+	* functions.texi: Regenerated.
+
 2003-05-07  Josef Zlomek  <zlomekj@suse.cz>
 
 	* splay-tree.c (splay_tree_predecessor): Fix comment.
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index 4261d8646761901badbbfb05048607b969f6b0e1..b34c20409e31058caae7b76eb37a194f29546ed2 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -337,13 +337,19 @@ or zero if it is not.  Note that the value you pass will be cast to
 @end deftypefn
 
 @c hex.c:42
-@deftypefn Extension int hex_value (int @var{c})
+@deftypefn Extension unsigned int hex_value (int @var{c})
 
 Returns the numeric equivalent of the given character when interpreted
 as a hexidecimal digit.  The result is undefined if you pass an
 invalid hex digit.  Note that the value you pass will be cast to
 @code{unsigned char} within the macro.
 
+The @code{hex_value} macro returns @code{unsigned int}, rather than
+signed @code{int}, to make it easier to use in parsing addresses from
+hex dump files: a signed @code{int} would be sign-extended when
+converted to a wider unsigned type --- like @code{bfd_vma}, on some
+systems.
+
 @end deftypefn
 
 @c index.c:5
diff --git a/libiberty/hex.c b/libiberty/hex.c
index 5f8229253494de21455e83b86766ca9e5002de11..f425509be75c0d510addeb7f3c9578c30a5800e1 100644
--- a/libiberty/hex.c
+++ b/libiberty/hex.c
@@ -39,13 +39,19 @@ or zero if it is not.  Note that the value you pass will be cast to
 
 @end deftypefn
 
-@deftypefn Extension int hex_value (int @var{c})
+@deftypefn Extension unsigned int hex_value (int @var{c})
 
 Returns the numeric equivalent of the given character when interpreted
 as a hexidecimal digit.  The result is undefined if you pass an
 invalid hex digit.  Note that the value you pass will be cast to
 @code{unsigned char} within the macro.
 
+The @code{hex_value} macro returns @code{unsigned int}, rather than
+signed @code{int}, to make it easier to use in parsing addresses from
+hex dump files: a signed @code{int} would be sign-extended when
+converted to a wider unsigned type --- like @code{bfd_vma}, on some
+systems.
+
 @end deftypefn
 
 @undocumented _hex_array_size
@@ -60,7 +66,7 @@ invalid hex digit.  Note that the value you pass will be cast to
   && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 \
   && EOF == -1
 
-const char _hex_value[_hex_array_size] =
+const unsigned char _hex_value[_hex_array_size] =
 {
   _hex_bad, _hex_bad, _hex_bad, _hex_bad,   /* NUL SOH STX ETX */
   _hex_bad, _hex_bad, _hex_bad, _hex_bad,   /* EOT ENQ ACK BEL */
@@ -139,7 +145,7 @@ const char _hex_value[_hex_array_size] =
 
 #else
 
-char _hex_value[_hex_array_size];
+unsigned char _hex_value[_hex_array_size];
 
 #endif /* not ASCII */