Fix for Bug 3671 - QEMU GDB stub listens on IPv6-only port on Windows 7
The connection string used by the GDB stub does not specify which
version of the Internet Protocol should be used by the port on
which it listens. On host platforms with IPv6 support, such as
Windows 7, this means that the stub listens on an IPv6-only port.
Since the GDB client uses IPv4, this means that the client cannot
connect to QEMU.
/*
* verneed.h - copy versioning information.
* Copyright (C) 2001 - 2006 Michael Riepe
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef lint
static const char verneed_h_rcsid[] = "@(#) $Id: verneed.h,v 1.12 2006/07/27 22:40:03 michael Exp $";
#endif /* lint */
#if VER_NEED_CURRENT != 1
#error libelf currently does not support VER_NEED_CURRENT != 1
#endif /* VER_NEED_CURRENT != 1 */
#if TOFILE
static void
__store_vernaux(vernaux_ftype *dst, const vernaux_mtype *src, unsigned enc) {
if (enc == ELFDATA2LSB) {
__store_u32L(dst->vna_hash, src->vna_hash);
__store_u16L(dst->vna_flags, src->vna_flags);
__store_u16L(dst->vna_other, src->vna_other);
__store_u32L(dst->vna_name, src->vna_name);
__store_u32L(dst->vna_next, src->vna_next);
}
else {
__store_u32M(dst->vna_hash, src->vna_hash);
__store_u16M(dst->vna_flags, src->vna_flags);
__store_u16M(dst->vna_other, src->vna_other);
__store_u32M(dst->vna_name, src->vna_name);
__store_u32M(dst->vna_next, src->vna_next);
}
}
static void
__store_verneed(verneed_ftype *dst, const verneed_mtype *src, unsigned enc) {
if (enc == ELFDATA2LSB) {
__store_u16L(dst->vn_version, src->vn_version);
__store_u16L(dst->vn_cnt, src->vn_cnt);
__store_u32L(dst->vn_file, src->vn_file);
__store_u32L(dst->vn_aux, src->vn_aux);
__store_u32L(dst->vn_next, src->vn_next);
}
else {
__store_u16M(dst->vn_version, src->vn_version);
__store_u16M(dst->vn_cnt, src->vn_cnt);
__store_u32M(dst->vn_file, src->vn_file);
__store_u32M(dst->vn_aux, src->vn_aux);
__store_u32M(dst->vn_next, src->vn_next);
}
}
typedef vernaux_mtype vernaux_stype;
typedef vernaux_ftype vernaux_dtype;
typedef verneed_mtype verneed_stype;
typedef verneed_ftype verneed_dtype;
typedef align_mtype verneed_atype;
#define copy_vernaux_srctotmp(d, s, e) (*(d) = *(s))
#define copy_vernaux_tmptodst(d, s, e) __store_vernaux((d), (s), (e))
#define copy_verneed_srctotmp(d, s, e) (*(d) = *(s))
#define copy_verneed_tmptodst(d, s, e) __store_verneed((d), (s), (e))
#define translator_suffix _tof
#else /* TOFILE */
static void
__load_vernaux(vernaux_mtype *dst, const vernaux_ftype *src, unsigned enc) {
if (enc == ELFDATA2LSB) {
dst->vna_hash = __load_u32L(src->vna_hash);
dst->vna_flags = __load_u16L(src->vna_flags);
dst->vna_other = __load_u16L(src->vna_other);
dst->vna_name = __load_u32L(src->vna_name);
dst->vna_next = __load_u32L(src->vna_next);
}
else {
dst->vna_hash = __load_u32M(src->vna_hash);
dst->vna_flags = __load_u16M(src->vna_flags);
dst->vna_other = __load_u16M(src->vna_other);
dst->vna_name = __load_u32M(src->vna_name);
dst->vna_next = __load_u32M(src->vna_next);
}
}
static void
__load_verneed(verneed_mtype *dst, const verneed_ftype *src, unsigned enc) {
if (enc == ELFDATA2LSB) {
dst->vn_version = __load_u16L(src->vn_version);
dst->vn_cnt = __load_u16L(src->vn_cnt);
dst->vn_file = __load_u32L(src->vn_file);
dst->vn_aux = __load_u32L(src->vn_aux);
dst->vn_next = __load_u32L(src->vn_next);
}
else {
dst->vn_version = __load_u16M(src->vn_version);
dst->vn_cnt = __load_u16M(src->vn_cnt);
dst->vn_file = __load_u32M(src->vn_file);
dst->vn_aux = __load_u32M(src->vn_aux);
dst->vn_next = __load_u32M(src->vn_next);
}
}
typedef vernaux_ftype vernaux_stype;
typedef vernaux_mtype vernaux_dtype;
typedef verneed_ftype verneed_stype;
typedef verneed_mtype verneed_dtype;
typedef align_ftype verneed_atype;
#define copy_vernaux_srctotmp(d, s, e) __load_vernaux((d), (s), (e))
#define copy_vernaux_tmptodst(d, s, e) (*(d) = *(s))
#define copy_verneed_srctotmp(d, s, e) __load_verneed((d), (s), (e))
#define copy_verneed_tmptodst(d, s, e) (*(d) = *(s))
#define translator_suffix _tom
#endif /* TOFILE */
#define cat3(a,b,c) a##b##c
#define xlt3(p,e,s) cat3(p,e,s)
#define xltprefix(x) xlt3(x,_,class_suffix)
#define translator(x,e) xlt3(xltprefix(_elf_##x),e,translator_suffix)
static size_t
xlt_verneed(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc) {
size_t off;
if (sizeof(verneed_stype) != sizeof(verneed_dtype)
|| sizeof(vernaux_stype) != sizeof(vernaux_dtype)) {
/* never happens for ELF v1 and Verneed v1 */
seterr(ERROR_UNIMPLEMENTED);
return (size_t)-1;
}
/* size translation shortcut */
if (dst == NULL) {
return n;
}
if (src == NULL) {
seterr(ERROR_NULLBUF);
return (size_t)-1;
}
off = 0;
while (off + sizeof(verneed_stype) <= n) {
const verneed_stype *svn;
verneed_dtype *dvn;
verneed_mtype vn;
size_t acount;
size_t aoff;
/*
* check for proper alignment
*/
if (off % sizeof(verneed_atype)) {
seterr(ERROR_VERNEED_FORMAT);
return (size_t)-1;
}
/*
* copy and check src
*/
svn = (verneed_stype*)(src + off);
dvn = (verneed_dtype*)(dst + off);
copy_verneed_srctotmp(&vn, svn, enc);
if (vn.vn_version < 1
|| vn.vn_version > VER_NEED_CURRENT) {
seterr(ERROR_VERNEED_VERSION);
return (size_t)-1;
}
if (vn.vn_cnt < 1
|| vn.vn_aux == 0) {
seterr(ERROR_VERNEED_FORMAT);
return (size_t)-1;
}
copy_verneed_tmptodst(dvn, &vn, enc);
/*
* copy aux array
*/
aoff = off + vn.vn_aux;
for (acount = 0; acount < vn.vn_cnt; acount++) {
const vernaux_stype *svna;
vernaux_dtype *dvna;
vernaux_mtype vna;
/*
* are we still inside the buffer limits?
*/
if (aoff + sizeof(vernaux_stype) > n) {
break;
}
/*
* check for proper alignment
*/
if (aoff % sizeof(verneed_atype)) {
seterr(ERROR_VERNEED_FORMAT);
return (size_t)-1;
}
/*
* copy and check src
*/
svna = (vernaux_stype*)(src + aoff);
dvna = (vernaux_dtype*)(dst + aoff);
copy_vernaux_srctotmp(&vna, svna, enc);
copy_vernaux_tmptodst(dvna, &vna, enc);
/*
* advance to next vernaux
*/
if (vna.vna_next == 0) {
/* end of list */
break;
}
aoff += vna.vna_next;
}
/*
* advance to next verneed
*/
if (vn.vn_next == 0) {
/* end of list */
break;
}
off += vn.vn_next;
}
return n;
}
size_t
translator(verneed,L11)(unsigned char *dst, const unsigned char *src, size_t n) {
return xlt_verneed(dst, src, n, ELFDATA2LSB);
}
size_t
translator(verneed,M11)(unsigned char *dst, const unsigned char *src, size_t n) {
return xlt_verneed(dst, src, n, ELFDATA2MSB);
}