go编译的c-shared库,在新唐ARM926EJ-S rev 5 (v5l)芯片上引用报Segmentation fault,如何解?

gibbsqi · · 744 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在X64的linux机器上,使用新塘的交叉编译环境,编译了一个很简单的C可调用的动态测试库。

go的版本为1.11.5

7f67ceea263b8c0ad9ce11dd61a3bf0f.png
代码如下:

package main

/*

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#include<stdbool.h>

#define RETURN_OK                                         1

#define RETURN_ERROR_INPUTPARAM                           1001

typedef struct{
    char version[256];
    uint16_t size;
}VersionInfo;
*/
import "C"

import "fmt"

//export GetVersion
func GetVersion() C.int {
  fmt.Println("GetVersion In")
  return C.int(1)
}


func main() {

}

上面代码保存为versiontest.go,通过编译命令

go build -buildmode=c-shared -o libversiontest.so versiontest.go

生成 libversiontest.so和libversiontest.h文件

libversiontest.h文件内容如下:

/* Code generated by cmd/cgo; DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-prolog"

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */


#line 3 "versiontest.go"


#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#include<stdbool.h>

#define RETURN_OK                                         1
/* Code generated by cmd/cgo; DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-prolog"

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */


#line 3 "versiontest.go"


#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#include<stdbool.h>

#define RETURN_OK                                         1

#define RETURN_ERROR_INPUTPARAM                           1001

typedef struct{
    char version[256];
    uint16_t size;
}VersionInfo;

#line 1 "cgo-generated-wrapper"


/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];

typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern int GetVersion();

#ifdef __cplusplus
}
#endif
        

go编译环境设置:

GOARCH=arm

GOARM=5                  //因为芯片架构为 ARMV5TEJ

CGO_ENABLED=1

CC和CXX设置为新唐提供的交叉编译环境中的编译器。

其他为默认设置。

 

编译可执行测试程序 testversion

编辑 testversion.c

#include "libversiontest.h"

int main(){
  GetVersion();

  return 1;
}

libversiontest.h和libversiontest.so都拷到testversion.c同一个目录下。

通过新塘gcc命令

arm-linux-gcc -I./ -L./ -lversiontest -o testversion testversion.c

生成testversion可执行程序。拷贝到新塘芯片上运行。报Segmentation fault

 

通过gdb查看,出错在

上传不了图片,直接手写了

Program received signal SIGILL, Illegal instruction.
_rt0_arm_lib () at /usr/local/go/src/runtime/asm_arm.s:46
46              MOVD    F8,  (40+8*0)(R13)

 

查看了asm_arm.s文件,截取了42~57行代码,如下

	// Skip floating point registers on GOARM < 6.                        //42
	MOVB    runtime·goarm(SB), R11                                        //43
	CMP	$6, R11                                                           //44
	BLT	skipfpsave                                                        //45
	MOVD	F8, (40+8*0)(R13)                                             //46
	MOVD	F9, (40+8*1)(R13)
	MOVD	F10, (40+8*2)(R13)
	MOVD	F11, (40+8*3)(R13)
	MOVD	F12, (40+8*4)(R13)
	MOVD	F13, (40+8*5)(R13)
	MOVD	F14, (40+8*6)(R13)
	MOVD	F15, (40+8*7)(R13)
skipfpsave:                                                              //54
	// Save argc/argv.                                                   //55
	MOVW	R0, _rt0_arm_lib_argc<>(SB)                                  //56
	MOVW	R1, _rt0_arm_lib_argv<>(SB)                                  //57

出错在46行

 

同样的代码在树莓派 Pi 2 model B(arm V7架构)上可以正常运行。

 

麻烦各位大神看一下是什么原因导致的?


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

744 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传