1
0
mirror of https://github.com/golang/go synced 2024-11-12 00:20:22 -07:00

cmd/cgo: replace C.malloc with our own wrapper

This allows us to make two changes:

1. Force the argument type to be size_t, even on broken
   systems that declare malloc to take a ulong.

2. Call runtime.throw if malloc fails.
   (That is, the program crashes; it does not panic.)

Fixes #3403.
Fixes #5926.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/13413047
This commit is contained in:
Russ Cox 2013-09-11 11:30:08 -04:00
parent 89b26760d7
commit 397ba2cb4a
4 changed files with 48 additions and 3 deletions

View File

@ -187,6 +187,13 @@ func (f *File) saveRef(x interface{}, context string) {
error_(sel.Pos(), "cannot refer to errno directly; see documentation") error_(sel.Pos(), "cannot refer to errno directly; see documentation")
return return
} }
if goname == "_CMalloc" {
error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
return
}
if goname == "malloc" {
goname = "_CMalloc"
}
name := f.Name[goname] name := f.Name[goname]
if name == nil { if name == nil {
name = &Name{ name = &Name{

View File

@ -341,7 +341,7 @@ func (p *Package) Record(f *File) {
if p.Name[k] == nil { if p.Name[k] == nil {
p.Name[k] = v p.Name[k] = v
} else if !reflect.DeepEqual(p.Name[k], v) { } else if !reflect.DeepEqual(p.Name[k], v) {
error_(token.NoPos, "inconsistent definitions for C.%s", k) error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
} }
} }
} }

View File

@ -331,7 +331,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
} }
// Builtins defined in the C prolog. // Builtins defined in the C prolog.
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
if *gccgo { if *gccgo {
// Gccgo style hooks. // Gccgo style hooks.
@ -476,9 +476,27 @@ func (p *Package) writeOutput(f *File, srcfile string) {
fgcc.Close() fgcc.Close()
} }
// fixGo convers the internal Name.Go field into the name we should show
// to users in error messages. There's only one for now: on input we rewrite
// C.malloc into C._CMalloc, so change it back here.
func fixGo(name string) string {
if name == "_CMalloc" {
return "malloc"
}
return name
}
var isBuiltin = map[string]bool{
"_Cfunc_CString": true,
"_Cfunc_GoString": true,
"_Cfunc_GoStringN": true,
"_Cfunc_GoBytes": true,
"_Cfunc__CMalloc": true,
}
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
name := n.Mangle name := n.Mangle
if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] { if isBuiltin[name] || p.Written[name] {
// The builtins are already defined in the C prolog, and we don't // The builtins are already defined in the C prolog, and we don't
// want to duplicate function definitions we've already done. // want to duplicate function definitions we've already done.
return return
@ -1101,6 +1119,8 @@ __cgo_size_assert(double, 8)
` `
const builtinProlog = ` const builtinProlog = `
#include <sys/types.h> /* for size_t below */
/* Define intgo when compiling with GCC. */ /* Define intgo when compiling with GCC. */
#ifdef __PTRDIFF_TYPE__ #ifdef __PTRDIFF_TYPE__
typedef __PTRDIFF_TYPE__ intgo; typedef __PTRDIFF_TYPE__ intgo;
@ -1116,6 +1136,7 @@ _GoString_ GoString(char *p);
_GoString_ GoStringN(char *p, int l); _GoString_ GoStringN(char *p, int l);
_GoBytes_ GoBytes(void *p, int n); _GoBytes_ GoBytes(void *p, int n);
char *CString(_GoString_); char *CString(_GoString_);
void *_CMalloc(size_t);
` `
const cProlog = ` const cProlog = `
@ -1153,6 +1174,13 @@ void
p[s.len] = 0; p[s.len] = 0;
FLUSH(&p); FLUSH(&p);
} }
void
·_Cfunc__CMalloc(uintptr n, int8 *p)
{
p = runtime·cmalloc(n);
FLUSH(&p);
}
` `
const cPrologGccgo = ` const cPrologGccgo = `
@ -1193,6 +1221,14 @@ Slice GoBytes(char *p, int32_t n) {
struct __go_string s = { (const unsigned char *)p, n }; struct __go_string s = { (const unsigned char *)p, n };
return __go_string_to_byte_array(s); return __go_string_to_byte_array(s);
} }
extern void runtime_throw(const char *):
void *Cmalloc(size_t n) {
void *p = malloc(n);
if(p == NULL)
runtime_throw("runtime: C malloc failed");
return p;
}
` `
func (p *Package) gccExportHeaderProlog() string { func (p *Package) gccExportHeaderProlog() string {

View File

@ -198,6 +198,8 @@ runtime·cmalloc(uintptr n)
a.n = n; a.n = n;
a.ret = nil; a.ret = nil;
runtime·cgocall(_cgo_malloc, &a); runtime·cgocall(_cgo_malloc, &a);
if(a.ret == nil)
runtime·throw("runtime: C malloc failed");
return a.ret; return a.ret;
} }