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:
parent
89b26760d7
commit
397ba2cb4a
@ -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{
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user